Hi,

Action proxies were born as a fork to notification proxies [1]. Both were attempts to get rid of invariant checks which have some cost. It's probably too late to bring such a change in the proxy design, but I have given more thoughts to it, so I'll share it, in the hope it'll fuel people's thoughts on proxies. I had issues with potential dangers of action proxies, but they're isolated to the handler author and only in already complex cases. Since proxies are a expert feature, the additional complexity in already complex cases is probably acceptable. Tom mentioned a per-trap-invocation cost [2]. Some ideas can make this cost disappear or so small it becomes acceptable.

In my experience, a lot of traps end with the statement:
    return Reflect.trap(...trapArgs)
It would be nice if this was made implicit. Notification proxies allow for this implicity. It would be nice if action proxies did too.

# Proposal

The action is the equivalent of "Reflect.trap(...trapArgs)". It is optional to call it. There is one action function per trap (not per invocation, only per trap type). When called, the "action" performs "Reflect.trap(...trapArgs)", stores the value in a slot and returns the value or throws.

Answers to Mark's questions:
1) what happens if the trap does not call action?
=> Exactly the same thing than with notification proxies: an implicit
    return Reflect.trap(...trapArgs)

2) what happens if the trap calls action more than once?
=> The best thing I've come up with is to make the function stateful (keep in mind that it's a theorical model, I'll talk optimizations below) and have one slot per trap invocation. Calling action fills the slot with the return value, the end of trap invocation empties the slot to use it as termination value (return value or boolean). This slot semantics is necessary anyway for action proxies (to remember the values to return in case of nested proxies).
So calling twice just changes the slot value.
Calling the action outside of a related trap invocation timeframe throws (no slot to fill in)

3) do actions ever return anything, in case the trap wants to pay attention to it?
=> yes, the return value of Reflect.trap(...trapArgs)

4) are there any return values from the trap that the proxy would pay attention to?
=> No. The return value is ignored.

5) if the original operation performed by action throws, should the action still just return to the trap normally?
=> No, forward the thrown exception.

6) what happens if the trap throws rather that returning?
=> The error thrown is forwarded to the caller, regardless of whether action has been called.

# Stateful per-trap function and abusive authority
What if malicious code gets all action functions and call them maliciously? In order to be malicious, the code would have to call the function in the middle of a trap invocation. The effect of the trap is Reflect.trap(...trapArgs) (not even change the return value) which was planned to be done implicitly or explicitly anyway. The attack case is when action had been called, modification was performed on the target and action wasn't planned to be called after the modification (and the attacker does call it within the invocation timeframe). Arguably, this is so subtle, harmless and easy to protect against that stateful actions can't be considered as abusive authority.

# Optimization opportunities

Since the calling the action is optional, before-traps won't even call it, won't even mention it, so the trap-invocation-slot semantics can be bypassed and the cost of this kind of action proxy is equivalent to notification proxies.

# Conclusion

This type of action proxy is sort of the fusion between notification proxies and original action proxies. By design, they remove the need for invariant checks. Their cost is one function per trap and the slot-per-trap-invocation semantics which will be ignored if the action isn't called explicitly. For the handler author, there is an additional action argument for each trap which is a bit boilerplate-y, but you only need it if you call it.

I feel it could work. Too late?

David

[1] https://mail.mozilla.org/pipermail/es-discuss/2012-December/026774.html
[2] https://mail.mozilla.org/pipermail/es-discuss/2012-December/026779.html
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to