📄 class.js
字号:
//if (nativeArguments == null && nativeArguments != false && args && args.constructor && // args.constructor.nativeType == 2) //{ // this.logWarn("substitute arguments passed, but native arguments object " + // "not passed as third parameter"); //} // overall plan: look through the inheritance chain for a method that differs from the // implementation in this instance, and call that // get the prototype for the last method of this name that called Super(). Null for // the first call to Super this._lastProto = isc.Class._getLastProto(methodName, this); // set flag to tell invokeSuper it's being called by external Super and needs to pick // up extra arguments from instance flags this._externalSuper = true; return this.invokeSuper(null, methodName); }, // observation and timers may replace a function with a generated function, storing the // original function in another slot. We need to find the original function because // otherwise, when we look up the superclass chain to find a differing implementation, we'd // be using the auto-generated function, and so think all superclasses had differing // implementations. // Note that both observation and timing indirects can be installed on classes as well as // instances. _getOriginalMethod : function (methodName, theProto) { var method = theProto[methodName]; while (method && method._origMethodSlot) { //this.logWarn("indirect installed on: " + theProto + ": " + this.echoLeaf(method)); method = theProto[method._origMethodSlot]; } return method; }, // high speed implementation of Super used by internal callers, where the class and method // of the calling function are directly passed in. Calls to external Super can be freely // mixed with calls to invokeSuper because they store the same state. // // Extremely critical path code sometimes calls Super like so: // isc.StatefulCanvas._instancePrototype.initWidget.call(this); // This is safe only if there are no calls to external Super() in any superclass // implementations. If there are, with the lack of any stored lastProto, inter-recursion // will be falsely detected and the leaf implementation will be called. invokeSuper : function (clazz, methodName, a,b,c,d,e,f,g,h) { // static mode (class methods calling Super) var staticSuper = this._isClassObject; var externalSuper = this._externalSuper; this._externalSuper = null; var nativeArguments = this._nativeArguments; this._nativeArguments = null; var lastProto; if (externalSuper) { lastProto = this._lastProto; this._lastProto == null; } else { // for framework code calling invokeSuper, null indicates instance override if (clazz != null) { // in static mode, protos are class objects lastProto = staticSuper ? clazz : clazz._instancePrototype; } } // figure out the method that is calling Super in order to compare the implementation // against superclass implementation to find out when a superclass implementation differs var methodCallingSuper, nextProto; if (lastProto == null) { methodCallingSuper = isc.Class._getOriginalMethod(methodName, this); // in static mode, there's no such thing as an instance override nextProto = staticSuper ? this : this.getPrototype(); //if (methodName == "draw") { // this.logWarn("new Super call, method calling super: " + // this.echoLeaf(methodCallingSuper)); //} } else { methodCallingSuper = isc.Class._getOriginalMethod(methodName, lastProto); if (staticSuper) { // static mode - get superclass classObject nextProto = lastProto._superClass; } else { // instance mode - get superclass instancePrototype nextProto = lastProto._classObject._superClass._instancePrototype; } if (nativeArguments && nativeArguments.callee != null && nativeArguments.callee != methodCallingSuper) { //this.logWarn("recursion detected: to continue current super chain caller" + // " should be: " + this.echoLeaf(methodCallingSuper) + // " but caller is: " + this.echoLeaf(nativeArguments.callee)); methodCallingSuper = isc.Class._getOriginalMethod(methodName, this); nextProto = staticSuper ? this : this.getPrototype(); } } // count all calls to externalSuper //if (externalSuper) { // var callCounts = isc._superCallCount = isc._superCallCount || [], // fullName = isc.Func.getName(methodCallingSuper); // // var record = callCounts.find("fullName", fullName); // if (record) record.callCount++; // else callCounts.add({fullName:fullName, callCount:1}); //} //this.logWarn("methodCallingSuper: " + this.echoLeaf(methodCallingSuper) + // ", lastProto: " + lastProto + // ", nextProto: " + nextProto); // find the next superclass implementation nextProto = isc.Class._getNextImplementingSuper(methodCallingSuper, nextProto, methodName, staticSuper); if (nextProto == null) { // failed to find a superclass implementation if (isc.Log) isc.Log.logWarn("Call to Super for method: " + methodName + " failed on: " + this + ": couldn't find a superclass implementation of : " + (lastProto ? lastProto.Class : this.Class) + "." + methodName + this.getStackTrace()); return null; } // we found a superclass implementation var superClassImpl = nextProto[methodName]; //if (methodName == "draw") { // this.logWarn("about to call: " + this.echoLeaf(superClassImpl) + // ", call chain: " + superCallChains); //} isc.Class._addProto(methodName, nextProto, this); // NOTE: it's normal that we're invoke an indirect (an observation or timer for // instance), which will invoke the original method for us - it's just when comparing // methods that we have to avoid using the indirects //if (superClassImpl._origMethodSlot) { // this.logWarn("invoking indirect: " + this.echoLeaf(superClassImpl) + // " found on prototype: " + nextProto); //} // call the superclass implementation on "this" var returnVal; if (externalSuper) { // for external callers, use apply() in order to preserve arguments.length just in // case external code contains a function that uses arguments.length and gets // called as Super if (nativeArguments) { returnVal = superClassImpl.apply(this, nativeArguments); } else { returnVal = superClassImpl.apply(this); } } else { returnVal = superClassImpl.call(this, a,b,c,d,e,f,g,h); } isc.Class._clearLastProto(methodName, this); // and return the value returned from the apply return returnVal; }, _getLastProto : function (methodName, obj) { var superCalls = obj._superCalls, protoList = superCalls == null ? null : superCalls[methodName]; //this.logWarn("for method: " + methodName + " chain is: " + protoList); if (isc.isAn.Array(protoList)) return protoList.last(); return protoList; }, _clearLastProto : function (methodName, obj) { var superCalls = obj._superCalls, protoList = superCalls[methodName]; if (protoList == null) { return; } // clear single item if (!isc.isAn.Array(protoList)) { superCalls[methodName] = null; } else { // shorten array, then remove if zero length protoList.length = Math.max(0, protoList.length-1); if (protoList.length == 0) superCalls[methodName] = null; } }, _addProto : function (methodName, newProto, obj) { var superCalls = obj._superCalls = obj._superCalls || {}, protoList = superCalls[methodName]; if (protoList == null) { superCalls[methodName] = newProto; } else { if (isc.isAn.Array(protoList)) protoList.add(newProto); else superCalls[methodName] = [protoList, newProto]; } }, //> @classMethod Class.map() // // Call <code>method</code> on each item in <code>argsList</code> and return the Array of results. // // @param methodName (string) // Name of the method on this instance which should be called on each element of the Array // @param items (Array) // Array of items to call the method on // // @return (Array) Array of results, one per element in the passed "items" Array // @visibility external //< map : function (methodName, items, arg1, arg2, arg3, arg4, arg5) { if (methodName == null) return items; var results = []; for (var i = 0; i < items.length; i++) { results.add(this[methodName](items[i], arg1, arg2, arg3, arg4, arg5)); } return results; }, //> @classMethod Class.getInstanceProperty() // // Gets a named property from the instance defaults for this object. // // @param property (string) name of the property to return // @visibility external //< getInstanceProperty : function (property) { var value = this._instancePrototype[property]; return value; }, //> @classMethod Class.setInstanceProperty() // // Sets a named property from the instance defaults for this object. // // @param property (string) name of the property to return // @param value (any) value to set to // @visibility external //< setInstanceProperty : function (property, value) { this._instancePrototype[property] = value; }, getArgString : function (methodName) { // check for a string method definition var argString = this._stringMethodRegistry[methodName]; var undef; if (argString !== undef) return argString || isc.emptyString; // get the arguments from the method definition (very very slow!) var method = this.getInstanceProperty(methodName); //if (method == null || !isc.isA.Function(method)) return ""; if (method == null) return ""; return isc.Func.getArgString(method); }, // Callbacks and Eval()ing // --------------------------------------------------------------------------------------- //> @type Callback // A <code>Callback</code> is an arbitrary action to be fired - usually passed into a // method to be fired asynchronously as a notificaction of some event.<br> // The <code>callback</code> can be defined in the following formats:<ul> // <li>a function</li> // <li>A string containing an expression to evaluate</li> // <li>An object with the following properties:<br> // - target: fire in the scope of this target - when the action fires, // the target will be available as <code>this</code>.<br> // - methodName: if specified we'll check for a method on the target object with this // name.<br> // </li></ul> // <code>Callbacks</code> are fired via the +link{classMethod:Class.fireCallback()} method, which allows // named parameters to be passed into the callback at runtime. If the Callback was specified // as a string of script, these parameters are available as local variables at eval time.<br> // For specific SmartClient methods that make use of <code>Callback</code> objects, see // local documentation for information on parameters and scope. // @visibility external //< //> @classMethod Class.fireCallback() // // Fire some arbitrary action specified as a +link{type:Callback}. // Returns the value returned by the action. // // @param callback (Callback) Action to fire. // @param [argNames] (string) Comma separated string of variable names. If the callback // passed in was a string of script, any arguments passed to the // callback will be available as local variables with these names. // @param [args] (array) Array of arguments to pass to the mthod. Note that the number // of arguments should match the number of argNames. // @param [target] (object) If specified the callback will be evaluated in the scope of this // object - the <code>this</code> keyword will be a pointer to this // target when the callback is fired. // @return (any) returns the value returned by the callback method passed in. // @visibility external //< fireCallback : function (callback, argNames, args, target, catchErrors) { arguments.__this = this; if (callback == null) return; var undef; if (argNames == null) argNames = undef; var method = callback; if (isc.isA.String(callback)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -