(Separate idea, separate post:)
The main (may I say the only?) use case of ProtoObject is to have a minimum superclass for generic proxies or decorators that are implemented generically using #doesNotUnderstand:.
Besides this mechanism, we also have #run:with:in: (see ObjectsAsMethodsExample).
Would it, hypothetically spoken, be worth a thought to implement some kind of hook on VM side/code simulation that is called before sending any message to a new receiver? Very pseudo:
MyCoolProxy >> #unmanagedPerformMessage: aMessage
"by implementing this method on a class, you tell the engine to call it before sending any message from a different object to the receiver
(we could also use something like #flush for this)"
aMessage = #inspectorClass ifTrue: [
^ aMessage sentTo: self "don't forward this message"].
self log: aMessage. "sending a message to the receiver does not invoke #unmanagedPerformMessage:"
"Finally ..."
^ aMessage sentTo: myTarget
Hi all! :-)
When we were fiddling around with some proxy implementations today, Marcel and I discovered an interesting set of issues regarding ProtoObjects.
Let's start with a concrete bug:
Code to reproduce <do it>:
ProtoObject new class.
Expected behavior:
DNU exception, because #class is implemented on Object only.
Actual behavior:
Outputs ProtoObject.
Even stranger: If you debug the method instead and simulate the #class send, you get a "simulated message class not understood" error.
If you subclass ProtoObject and override/forward #class, the results will deviate based on whether you are debugging or executing the code.
Some thoughts:
There are two options: Either to implement #class on ProtoObject (by moving the primitive definition up from Object), or to remove
it from the specialObjectsArray so that a send to #class is not compiled differently than a send to any other regular message.
This leads us to the rather general question: What special messages should an instance of ProtoObject understand?
We don't answer this question completely consistent at the moment: For example, #instVarAt: is implemented on Object, but #instVarsInclude: is implemented on ProtoObject. Again, it is a bit weird that the implementation of #instVarsInclude: calls #class which is implemented on Object only. And so it goes on: