|
26 | 26 |
|
27 | 27 | var cc = cc || {};
|
28 | 28 |
|
| 29 | +/** |
| 30 | + * Common getter setter configuration function |
| 31 | + * @function |
| 32 | + * @param {Object} proto A class prototype or an object to config<br/> |
| 33 | + * @param {String} prop Property name |
| 34 | + * @param {function} getter Getter function for the property |
| 35 | + * @param {function} setter Setter function for the property |
| 36 | + * @param {String} getterName Name of getter function for the property |
| 37 | + * @param {String} setterName Name of setter function for the property |
| 38 | + */ |
| 39 | +cc.defineGetterSetter = function (proto, prop, getter, setter, getterName, setterName) { |
| 40 | + if (proto.__defineGetter__) { |
| 41 | + getter && proto.__defineGetter__(prop, getter); |
| 42 | + setter && proto.__defineSetter__(prop, setter); |
| 43 | + } else if (Object.defineProperty) { |
| 44 | + var desc = {enumerable: false, configurable: true}; |
| 45 | + getter && (desc.get = getter); |
| 46 | + setter && (desc.set = setter); |
| 47 | + Object.defineProperty(proto, prop, desc); |
| 48 | + } else { |
| 49 | + throw new Error("browser does not support getters"); |
| 50 | + } |
| 51 | + |
| 52 | + if (!getterName && !setterName) { |
| 53 | + // Lookup getter/setter function |
| 54 | + var hasGetter = (getter != null), hasSetter = (setter != undefined), props = Object.getOwnPropertyNames(proto); |
| 55 | + for (var i = 0; i < props.length; i++) { |
| 56 | + var name = props[i]; |
| 57 | + |
| 58 | + if ((proto.__lookupGetter__ ? proto.__lookupGetter__(name) |
| 59 | + : Object.getOwnPropertyDescriptor(proto, name)) |
| 60 | + || typeof proto[name] !== "function") |
| 61 | + continue; |
| 62 | + |
| 63 | + var func = proto[name]; |
| 64 | + if (hasGetter && func === getter) { |
| 65 | + getterName = name; |
| 66 | + if (!hasSetter || setterName) break; |
| 67 | + } |
| 68 | + if (hasSetter && func === setter) { |
| 69 | + setterName = name; |
| 70 | + if (!hasGetter || getterName) break; |
| 71 | + } |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + // Found getter/setter |
| 76 | + var ctor = proto.constructor; |
| 77 | + if (getterName) { |
| 78 | + if (!ctor.__getters__) { |
| 79 | + ctor.__getters__ = {}; |
| 80 | + } |
| 81 | + ctor.__getters__[getterName] = prop; |
| 82 | + } |
| 83 | + if (setterName) { |
| 84 | + if (!ctor.__setters__) { |
| 85 | + ctor.__setters__ = {}; |
| 86 | + } |
| 87 | + ctor.__setters__[setterName] = prop; |
| 88 | + } |
| 89 | +}; |
| 90 | + |
| 91 | +/** |
| 92 | + * Create a new object and copy all properties in an exist object to the new object |
| 93 | + * @function |
| 94 | + * @param {object|Array} obj The source object |
| 95 | + * @return {Array|object} The created object |
| 96 | + */ |
| 97 | +cc.clone = function (obj) { |
| 98 | + // Cloning is better if the new object is having the same prototype chain |
| 99 | + // as the copied obj (or otherwise, the cloned object is certainly going to |
| 100 | + // have a different hidden class). Play with C1/C2 of the |
| 101 | + // PerformanceVirtualMachineTests suite to see how this makes an impact |
| 102 | + // under extreme conditions. |
| 103 | + // |
| 104 | + // Object.create(Object.getPrototypeOf(obj)) doesn't work well because the |
| 105 | + // prototype lacks a link to the constructor (Carakan, V8) so the new |
| 106 | + // object wouldn't have the hidden class that's associated with the |
| 107 | + // constructor (also, for whatever reasons, utilizing |
| 108 | + // Object.create(Object.getPrototypeOf(obj)) + Object.defineProperty is even |
| 109 | + // slower than the original in V8). Therefore, we call the constructor, but |
| 110 | + // there is a big caveat - it is possible that the this.init() in the |
| 111 | + // constructor would throw with no argument. It is also possible that a |
| 112 | + // derived class forgets to set "constructor" on the prototype. We ignore |
| 113 | + // these possibities for and the ultimate solution is a standardized |
| 114 | + // Object.clone(<object>). |
| 115 | + var newObj = (obj.constructor) ? new obj.constructor : {}; |
| 116 | + |
| 117 | + // Assuming that the constuctor above initialized all properies on obj, the |
| 118 | + // following keyed assignments won't turn newObj into dictionary mode |
| 119 | + // because they're not *appending new properties* but *assigning existing |
| 120 | + // ones* (note that appending indexed properties is another story). See |
| 121 | + // CCClass.js for a link to the devils when the assumption fails. |
| 122 | + for (var key in obj) { |
| 123 | + var copy = obj[key]; |
| 124 | + // Beware that typeof null == "object" ! |
| 125 | + if (((typeof copy) === "object") && copy && !(copy instanceof cc.Node) && !(copy instanceof HTMLElement)) { |
| 126 | + newObj[key] = cc.clone(copy); |
| 127 | + } else { |
| 128 | + newObj[key] = copy; |
| 129 | + } |
| 130 | + } |
| 131 | + return newObj; |
| 132 | +}; |
| 133 | + |
| 134 | +cc.inject = function (srcPrototype, destPrototype) { |
| 135 | + for (var key in srcPrototype) |
| 136 | + destPrototype[key] = srcPrototype[key]; |
| 137 | +}; |
| 138 | + |
29 | 139 | /**
|
30 | 140 | * @namespace
|
31 | 141 | * @name ClassManager
|
@@ -71,43 +181,63 @@ var ClassManager = {
|
71 | 181 | // don't run the init constructor)
|
72 | 182 | var prototype = Object.create(_super);
|
73 | 183 |
|
74 |
| - var classId = ClassManager.getNewID(); |
75 |
| - ClassManager[classId] = _super; |
76 | 184 | // Copy the properties over onto the new prototype. We make function
|
77 | 185 | // properties non-eumerable as this makes typeof === 'function' check
|
78 | 186 | // unnecessary in the for...in loop used 1) for generating Class()
|
79 | 187 | // 2) for cc.clone and perhaps more. It is also required to make
|
80 | 188 | // these function properties cacheable in Carakan.
|
81 |
| - var desc = { writable: true, enumerable: false, configurable: true }; |
82 |
| - |
83 |
| - prototype.__instanceId = null; |
84 |
| - |
85 |
| - // The dummy Class constructor |
86 |
| - function Class() { |
87 |
| - this.__instanceId = ClassManager.getNewInstanceId(); |
88 |
| - // All construction is actually done in the init method |
89 |
| - if (this.ctor) |
90 |
| - this.ctor.apply(this, arguments); |
91 |
| - } |
| 189 | + var desc = {writable: true, enumerable: false, configurable: true}; |
| 190 | + |
| 191 | + // The dummy Class constructor |
| 192 | + var Class; |
| 193 | + if (cc.game.config[cc.game.CONFIG_KEY.exposeClassName]) { |
| 194 | + var constructor = "(function " + (props._className || "Class") + " (arg0, arg1, arg2, arg3, arg4, arg5) {\n"; |
| 195 | + constructor += " this.__instanceId = ClassManager.getNewInstanceId();\n"; |
| 196 | + constructor += " if (this.ctor) {\n"; |
| 197 | + constructor += " switch (arguments.length) {\n"; |
| 198 | + constructor += " case 0: this.ctor(); break;\n"; |
| 199 | + constructor += " case 1: this.ctor(arg0); break;\n"; |
| 200 | + constructor += " case 3: this.ctor(arg0, arg1, arg2); break;\n"; |
| 201 | + constructor += " case 4: this.ctor(arg0, arg1, arg2, arg3); break;\n"; |
| 202 | + constructor += " case 5: this.ctor(arg0, arg1, arg2, arg3, arg4); break;\n"; |
| 203 | + constructor += " default: this.ctor.apply(this, arguments);\n"; |
| 204 | + constructor += " }\n"; |
| 205 | + constructor += " }\n"; |
| 206 | + constructor += "})"; |
| 207 | + Class = eval(constructor); |
| 208 | + } |
| 209 | + else { |
| 210 | + Class = function (arg0, arg1, arg2, arg3, arg4) { |
| 211 | + this.__instanceId = ClassManager.getNewInstanceId(); |
| 212 | + if (this.ctor) { |
| 213 | + switch (arguments.length) { |
| 214 | + case 0: this.ctor(); break; |
| 215 | + case 1: this.ctor(arg0); break; |
| 216 | + case 2: this.ctor(arg0, arg1); break; |
| 217 | + case 3: this.ctor(arg0, arg1, arg2); break; |
| 218 | + case 4: this.ctor(arg0, arg1, arg2, arg3); break; |
| 219 | + case 5: this.ctor(arg0, arg1, arg2, arg3, arg4); break; |
| 220 | + default: this.ctor.apply(this, arguments); |
| 221 | + } |
| 222 | + } |
| 223 | + }; |
| 224 | + } |
92 | 225 |
|
93 |
| - Class.id = classId; |
94 |
| - // desc = { writable: true, enumerable: false, configurable: true, |
95 |
| - // value: XXX }; Again, we make this non-enumerable. |
96 |
| - desc.value = classId; |
97 |
| - Object.defineProperty(prototype, '__pid', desc); |
| 226 | + desc.value = ClassManager.getNewID(); |
| 227 | + Object.defineProperty(prototype, '__pid', desc); |
98 | 228 |
|
99 |
| - // Populate our constructed prototype object |
100 |
| - Class.prototype = prototype; |
| 229 | + // Populate our constructed prototype object |
| 230 | + Class.prototype = prototype; |
101 | 231 |
|
102 |
| - // Enforce the constructor to be what we expect |
103 |
| - desc.value = Class; |
104 |
| - Object.defineProperty(Class.prototype, 'constructor', desc); |
| 232 | + // Enforce the constructor to be what we expect |
| 233 | + desc.value = Class; |
| 234 | + Object.defineProperty(prototype, 'constructor', desc); |
105 | 235 |
|
106 |
| - // Copy getter/setter |
107 |
| - this.__getters__ && (Class.__getters__ = cc.clone(this.__getters__)); |
108 |
| - this.__setters__ && (Class.__setters__ = cc.clone(this.__setters__)); |
| 236 | + // Copy getter/setter |
| 237 | + this.__getters__ && (Class.__getters__ = cc.clone(this.__getters__)); |
| 238 | + this.__setters__ && (Class.__setters__ = cc.clone(this.__setters__)); |
109 | 239 |
|
110 |
| - for(var idx = 0, li = arguments.length; idx < li; ++idx) { |
| 240 | + for (var idx = 0, li = arguments.length; idx < li; ++idx) { |
111 | 241 | var prop = arguments[idx];
|
112 | 242 | for (var name in prop) {
|
113 | 243 | var isFunc = (typeof prop[name] === "function");
|
@@ -179,114 +309,3 @@ var ClassManager = {
|
179 | 309 | };
|
180 | 310 | })();
|
181 | 311 |
|
182 |
| -/** |
183 |
| - * Common getter setter configuration function |
184 |
| - * @function |
185 |
| - * @param {Object} proto A class prototype or an object to config<br/> |
186 |
| - * @param {String} prop Property name |
187 |
| - * @param {function} getter Getter function for the property |
188 |
| - * @param {function} setter Setter function for the property |
189 |
| - * @param {String} getterName Name of getter function for the property |
190 |
| - * @param {String} setterName Name of setter function for the property |
191 |
| - */ |
192 |
| -cc.defineGetterSetter = function (proto, prop, getter, setter, getterName, setterName){ |
193 |
| - if (proto.__defineGetter__) { |
194 |
| - getter && proto.__defineGetter__(prop, getter); |
195 |
| - setter && proto.__defineSetter__(prop, setter); |
196 |
| - } else if (Object.defineProperty) { |
197 |
| - var desc = { enumerable: false, configurable: true }; |
198 |
| - getter && (desc.get = getter); |
199 |
| - setter && (desc.set = setter); |
200 |
| - Object.defineProperty(proto, prop, desc); |
201 |
| - } else { |
202 |
| - throw new Error("browser does not support getters"); |
203 |
| - } |
204 |
| - |
205 |
| - if(!getterName && !setterName) { |
206 |
| - // Lookup getter/setter function |
207 |
| - var hasGetter = (getter != null), hasSetter = (setter != undefined), props = Object.getOwnPropertyNames(proto); |
208 |
| - for (var i = 0; i < props.length; i++) { |
209 |
| - var name = props[i]; |
210 |
| - |
211 |
| - if( (proto.__lookupGetter__ ? proto.__lookupGetter__(name) |
212 |
| - : Object.getOwnPropertyDescriptor(proto, name)) |
213 |
| - || typeof proto[name] !== "function" ) |
214 |
| - continue; |
215 |
| - |
216 |
| - var func = proto[name]; |
217 |
| - if (hasGetter && func === getter) { |
218 |
| - getterName = name; |
219 |
| - if(!hasSetter || setterName) break; |
220 |
| - } |
221 |
| - if (hasSetter && func === setter) { |
222 |
| - setterName = name; |
223 |
| - if(!hasGetter || getterName) break; |
224 |
| - } |
225 |
| - } |
226 |
| - } |
227 |
| - |
228 |
| - // Found getter/setter |
229 |
| - var ctor = proto.constructor; |
230 |
| - if (getterName) { |
231 |
| - if (!ctor.__getters__) { |
232 |
| - ctor.__getters__ = {}; |
233 |
| - } |
234 |
| - ctor.__getters__[getterName] = prop; |
235 |
| - } |
236 |
| - if (setterName) { |
237 |
| - if (!ctor.__setters__) { |
238 |
| - ctor.__setters__ = {}; |
239 |
| - } |
240 |
| - ctor.__setters__[setterName] = prop; |
241 |
| - } |
242 |
| -}; |
243 |
| - |
244 |
| -/** |
245 |
| - * Create a new object and copy all properties in an exist object to the new object |
246 |
| - * @function |
247 |
| - * @param {object|Array} obj The source object |
248 |
| - * @return {Array|object} The created object |
249 |
| - */ |
250 |
| -cc.clone = function (obj) { |
251 |
| - // Cloning is better if the new object is having the same prototype chain |
252 |
| - // as the copied obj (or otherwise, the cloned object is certainly going to |
253 |
| - // have a different hidden class). Play with C1/C2 of the |
254 |
| - // PerformanceVirtualMachineTests suite to see how this makes an impact |
255 |
| - // under extreme conditions. |
256 |
| - // |
257 |
| - // Object.create(Object.getPrototypeOf(obj)) doesn't work well because the |
258 |
| - // prototype lacks a link to the constructor (Carakan, V8) so the new |
259 |
| - // object wouldn't have the hidden class that's associated with the |
260 |
| - // constructor (also, for whatever reasons, utilizing |
261 |
| - // Object.create(Object.getPrototypeOf(obj)) + Object.defineProperty is even |
262 |
| - // slower than the original in V8). Therefore, we call the constructor, but |
263 |
| - // there is a big caveat - it is possible that the this.init() in the |
264 |
| - // constructor would throw with no argument. It is also possible that a |
265 |
| - // derived class forgets to set "constructor" on the prototype. We ignore |
266 |
| - // these possibities for and the ultimate solution is a standardized |
267 |
| - // Object.clone(<object>). |
268 |
| - var newObj = (obj.constructor) ? new obj.constructor : {}; |
269 |
| - |
270 |
| - // Assuming that the constuctor above initialized all properies on obj, the |
271 |
| - // following keyed assignments won't turn newObj into dictionary mode |
272 |
| - // because they're not *appending new properties* but *assigning existing |
273 |
| - // ones* (note that appending indexed properties is another story). See |
274 |
| - // CCClass.js for a link to the devils when the assumption fails. |
275 |
| - for (var key in obj) { |
276 |
| - var copy = obj[key]; |
277 |
| - // Beware that typeof null == "object" ! |
278 |
| - if (((typeof copy) === "object") && copy && |
279 |
| - !(copy instanceof cc.Node) && !(copy instanceof HTMLElement)) { |
280 |
| - newObj[key] = cc.clone(copy); |
281 |
| - } else { |
282 |
| - newObj[key] = copy; |
283 |
| - } |
284 |
| - } |
285 |
| - return newObj; |
286 |
| -}; |
287 |
| - |
288 |
| -cc.inject = function(srcPrototype, destPrototype){ |
289 |
| - for(var key in srcPrototype) |
290 |
| - destPrototype[key] = srcPrototype[key]; |
291 |
| -}; |
292 |
| - |
|
0 commit comments