Richard Frith-Macdonald schrieb:
Well I could revert the 'fix'.
I assumed that it was safer to call -methodForSelector: on an object
than -instanceMethodForSelector: on a class, since any
implementation of
the former would have more information to work with (knowing details
about the instance) in cases where the underlaying class was
implementing a proxy to some other object.
Of course, in an ideal world every class *ought* to have a correct
and
reliable implementation of both methods ... I was just trying to go
for
the option which I thought most likely to be reliable in practice.
Well there are a few examples of classes on which you cannot not call
arbitrary methods at arbitrary times.
- NSAutoreleasePool itself raises on retain and autorelease and
therefor
cannot be added to collections.
And firing EOFaults (what actually happened to NSFaults? I remember
discussing those a once) will do exactly that. It generally implies
database access, creating many auto released objects to populate the
attribute instance variables including accessor methods which all
could
validly call autorelease.
I would want to add another special handling. EOFaults are indeed
not
standard ObjC constructs that require special treatment (Probably
like
NSProxy also). They try to be transparent objects but there are
some
rules. Just like one isn't allowed to send certain methods to
NSAutoreleasePool instances, EOFaults are also special. I don't
think
these optimizations should be allowed to have such an impact on the
semantics other features. I think we had a good compromise with
+instanceMethodForSelector: (but we my still need to improve on that
within GDL2). But asking us handle -methodForSelector for an
optimization seems to be rather tough.
I'm happy to revert the change ... but at the same time I think
EOFault
should have properly working implementations of all the basic
methods of
NSObject and NSProxy. However, I have no knowledge of the
complexity of
EOFault, so I don't know how much work that would be ...
Just let me know what you want me to do.
There are defined methods that do /not/ cause an EOFault to fire and
they have been carefully selected to cope with Foundation's paradigms.
They are:
-retain
-release
-autorelease
-retainCount
-class
-superclass
-isKindOfClass:
-isMemberOfClass
-conformsToProtocol:
-isProxy
-methodSignatureForSelector:
-respondsToSelector:
-zone
-doesNotRecognizeSelector:
These methods also don't fire the fault but they don't "hide" the fact
that the object has been faulted:
-description
-descriptionWithLocale:
-descriptionWithIndent:
-descriptionWithLocale:indent:
-eoDescription
-eoShallowDescription
(see:
http://developer.apple.com/documentation/LegacyTechnologies/WebObjects/WebObjects_4.5/System/Library/Frameworks/EOControl.framework/ObjC_classic/Classes/EOFault.html)
(http://tinyurl.com/ys3ebu)
everything else should fire the fault. In particular
methodForSelector:
should fire it so that you will get the implementation of the real
class
and insure that the real class is available. Yet the side effects of
firing the fault (which are valid in most contexts) aren't valid for
-emtpyPool. (see above)
NSAutoreleasePool is a special class that has semantics that effect
every Foundation based application / library. Especially -emptyPool
has
to be careful not to implicitly invoke methods that need an auto
release
pool in place. And there are other issues it needs to take into
account.
For example, if you were to attempt to obtain the class with -class
instead of GSObjCClass you'd get the target class instead of EOFault.
Then +instanceMethodForSelector: would give you the implementation of
the original object, yet you'd be invoking it while it is still
faulted.
I would argue that invoking /anything/ but -release (and
-retainCount/retain if necessary) is likely to be bug. But I have a
strong sympathy for the IMP caching when an object has a high retain
count. So I'm fine with the GSObjCClass/+instanceMethodForSelector:
approach even though this is already rather shady.
I really don't think -methodForSelector: should avoid fireing
depending
on the selector.
So, yes I do think the patch needs to reverted.