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.compileSuper=function(func, name, id){ 43 //make the func to a string 44 var str = func.toString(); 45 //find parameters 46 var pstart = str.indexOf('('); 47 var pend = str.indexOf(')'); 48 var params = str.substring(pstart+1, pend); 49 params = params.trim(); 50 51 //find function body 52 var bstart = str.indexOf('{'); 53 var bend = str.lastIndexOf('}'); 54 var str = str.substring(bstart+1, bend); 55 56 //now we have the content of the function, replace this._super 57 //find this._super 58 while(str.indexOf('this._super')!= -1) 59 { 60 var sp = str.indexOf('this._super'); 61 //find the first '(' from this._super) 62 var bp = str.indexOf('(', sp); 63 64 //find if we are passing params to super 65 var bbp = str.indexOf(')', bp); 66 var superParams = str.substring(bp+1, bbp); 67 superParams = superParams.trim(); 68 var coma = superParams? ',':''; 69 70 //find name of ClassManager 71 var Cstr = arguments.callee.ClassManager(); 72 73 //replace this._super 74 str = str.substring(0, sp)+ Cstr+'['+id+'].'+name+'.call(this'+coma+str.substring(bp+1); 75 } 76 return Function(params, str); 77 }; 78 ClassManager.compileSuper.ClassManager = ClassManager; 79 ClassManager.getNewID=function(){ 80 return this.id++; 81 }; 82 83 84 (function () { 85 var initializing = false, fnTest = /\b_super\b/; 86 var releaseMode = (document['ccConfig'] && document['ccConfig']['CLASS_RELEASE_MODE']) ? document['ccConfig']['CLASS_RELEASE_MODE'] : null; 87 if(releaseMode) { 88 console.log("release Mode"); 89 } 90 91 /** 92 * The base Class implementation (does nothing) 93 * @class 94 */ 95 cc.Class = function () { 96 }; 97 98 /** 99 * Create a new Class that inherits from this Class 100 * @param {object} prop 101 * @return {function} 102 */ 103 cc.Class.extend = function (prop) { 104 var _super = this.prototype; 105 106 // Instantiate a base Class (but only create the instance, 107 // don't run the init constructor) 108 var prototype = Object.create(_super); 109 110 var classId = ClassManager.getNewID(); 111 ClassManager[classId] = _super; 112 // Copy the properties over onto the new prototype. We make function 113 // properties non-eumerable as this makes typeof === 'function' check 114 // unneccessary in the for...in loop used 1) for generating Class() 115 // 2) for cc.clone and perhaps more. It is also required to make 116 // these function properties cacheable in Carakan. 117 var desc = { writable: true, enumerable: false, configurable: true }; 118 for (var name in prop) { 119 if(releaseMode && typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) { 120 desc.value = ClassManager.compileSuper(prop[name], name, classId); 121 Object.defineProperty(prototype, name, desc); 122 } else if(typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])){ 123 desc.value = (function (name, fn) { 124 return function () { 125 var tmp = this._super; 126 127 // Add a new ._super() method that is the same method 128 // but on the super-Class 129 this._super = _super[name]; 130 131 // The method only need to be bound temporarily, so we 132 // remove it when we're done executing 133 var ret = fn.apply(this, arguments); 134 this._super = tmp; 135 136 return ret; 137 }; 138 })(name, prop[name]); 139 Object.defineProperty(prototype, name, desc); 140 } else if(typeof prop[name] == "function") { 141 desc.value = prop[name]; 142 Object.defineProperty(prototype, name, desc); 143 } else{ 144 prototype[name] = prop[name]; 145 } 146 } 147 148 // The dummy Class constructor 149 function Class() { 150 // All construction is actually done in the init method 151 if (this.ctor) 152 this.ctor.apply(this, arguments); 153 } 154 155 Class.id = classId; 156 // desc = { writable: true, enumerable: false, configurable: true, 157 // value: XXX }; Again, we make this non-enumerable. 158 desc.value = classId; 159 Object.defineProperty(prototype, '__pid', desc); 160 161 // Populate our constructed prototype object 162 Class.prototype = prototype; 163 164 // Enforce the constructor to be what we expect 165 desc.value = Class; 166 Object.defineProperty(Class.prototype, 'constructor', desc); 167 168 // And make this Class extendable 169 Class.extend = arguments.callee; 170 171 //add implementation method 172 Class.implement = function (prop) { 173 for (var name in prop) { 174 prototype[name] = prop[name]; 175 } 176 }; 177 return Class; 178 }; 179 180 Function.prototype.bind = Function.prototype.bind || function (bind) { 181 var self = this; 182 return function () { 183 var args = Array.prototype.slice.call(arguments); 184 return self.apply(bind || null, args); 185 }; 186 }; 187 188 })(); 189 190 // 191 // Another way to subclass: Using Google Closure. 192 // The following code was copied + pasted from goog.base / goog.inherits 193 // 194 cc.inherits = function (childCtor, parentCtor) { 195 /** @constructor */ 196 function tempCtor() {} 197 tempCtor.prototype = parentCtor.prototype; 198 childCtor.superClass_ = parentCtor.prototype; 199 childCtor.prototype = new tempCtor(); 200 childCtor.prototype.constructor = childCtor; 201 202 // Copy "static" method, but doesn't generate subclasses. 203 // for( var i in parentCtor ) { 204 // childCtor[ i ] = parentCtor[ i ]; 205 // } 206 }; 207 cc.base = function(me, opt_methodName, var_args) { 208 var caller = arguments.callee.caller; 209 if (caller.superClass_) { 210 // This is a constructor. Call the superclass constructor. 211 ret = caller.superClass_.constructor.apply( me, Array.prototype.slice.call(arguments, 1)); 212 return ret; 213 } 214 215 var args = Array.prototype.slice.call(arguments, 2); 216 var foundCaller = false; 217 for (var ctor = me.constructor; 218 ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) { 219 if (ctor.prototype[opt_methodName] === caller) { 220 foundCaller = true; 221 } else if (foundCaller) { 222 return ctor.prototype[opt_methodName].apply(me, args); 223 } 224 } 225 226 // If we did not find the caller in the prototype chain, 227 // then one of two things happened: 228 // 1) The caller is an instance method. 229 // 2) This method was not called by the right caller. 230 if (me[opt_methodName] === caller) { 231 return me.constructor.prototype[opt_methodName].apply(me, args); 232 } else { 233 throw Error( 234 'cc.base called from a method of one name ' + 235 'to a method of a different name'); 236 } 237 }; 238 239 cc.concatObjectProperties = function(dstObject, srcObject){ 240 if(!dstObject) 241 dstObject = {}; 242 243 for(var selKey in srcObject){ 244 dstObject[selKey] = srcObject[selKey]; 245 } 246 return dstObject; 247 }; 248 249