[[SetInheritance]] (was: General comments response (was Re: ES6 Rev13 Review: MOP-refactoring, symbols, proxies, Reflect module))
On Monday, December 31, 2012, Tom Van Cutsem wrote:
That said, I think this issue is orthogonal to our choice of whether or not to expose "setPrototypeOf" as part of the MOP. Even if we do expose it, any sandbox that wants to take away the ability the set the prototype can simply poison Reflect.setPrototypeOf in addition to deleting Object.prototype.proto.
Ive realized this is actually a potentially serious flaw with the module
system with to how the builtin modules expose features. If you
introduce Reflect.setPrototypeOf (or more generally, anything exposed
as an export of
a system module) there is no way for something like SES (user level) to
remove access to it. There's no way to monkey patch these things or remove
them or add new features to them because the modules aren't externally
mutable. delete Reflect.setPrototypeOf is not currently an option.
On Dec 31, 2012, at 7:28 AM, Brandon Benvie wrote:
On Monday, December 31, 2012, Tom Van Cutsem wrote: That said, I think this issue is orthogonal to our choice of whether or not to expose "setPrototypeOf" as part of the MOP. Even if we do expose it, any sandbox that wants to take away the ability the set the prototype can simply poison Reflect.setPrototypeOf in addition to deleting Object.prototype.proto.
Ive realized this is actually a potentially serious flaw with the module system with to how the builtin modules expose features. If you introduce Reflect.setPrototypeOf (or more generally, anything exposed as an export of a system module) there is no way for something like SES (user level) to remove access to it. There's no way to monkey patch these things or remove them or add new features to them because the modules aren't externally mutable.
delete Reflect.setPrototypeOfis not currently an option.
I'll leave it to Dave or Sam to elaborate, but I don't think this is correct. My understanding, is that such censoring can be accomplished by configuring a module loader to return an alternative implementation of the "@Reflect" (or however it is identified) which could either not export Reflect.setPrototypeOf or export an alternative implementation.
2012/12/30 Allen Wirfs-Brock <allen at wirfs-brock.com>
Ok. I did a search for [[SetInheritance]] in the Rev13 draft and the only place this method was called was from Reflect.setPrototypeOf and the Proxy "setPrototypeOf" trap default. That's why I thought it could easily be removed. I now see the note that appendix B3.1 (specifying proto) is not yet up-to-date. Probably when it's updated, this part of the spec will also call [[SetInheritance]].
It seems there are two routes we can take a) Introduce a "setPrototypeOf" trap (as currently specified), with the invariant check that the new prototype must match that of the target if setPrototypeOf returns true (a return value of "false" would mean the proxy rejected the prototype change).
b) Not treat proto as a magical property on proxies, and get rid of the "setPrototypeOf" trap. This implies that aProxy.proto = val just triggers the "set" trap. This delegates the choice of whether to treat proto as magical or not to every individual proxy handler.
Reflect.setPrototypeOf is not essential and simply there to provide a point
I agree that if we take choice (a) (i.e. introduce a "setPrototypeOf" trap) then we should also have the corresponding Reflect.setPrototypeOf primitive.
Yep.
Agreed. Although we should make an effort to make it easy for sandboxes/dialects to remove the feature from the language.
That said, I think this issue is orthogonal to our choice of whether or not to expose "setPrototypeOf" as part of the MOP. Even if we do expose it, any sandbox that wants to take away the ability the set the prototype can simply poison Reflect.setPrototypeOf in addition to deleting Object.prototype.proto.
2012/12/30 Allen Wirfs-Brock <allen at wirfs-brock.com> > > On Dec 29, 2012, at 2:37 PM, Tom Van Cutsem wrote: > > * [[SetInheritance]]/Reflect.setPrototypeOf: I'm not sure this was > agreed upon. Especially since __proto__ is currently specified as a data > property. This means there is no setter that separately reifies the ability > to set the prototype. Thus, it's perfectly possible to just exclude > [[SetInheritance]] and Reflect.setPrototypeOf from the spec. > > No, [[SetInheritence]] needs to be part of the MOP. Certainly to define > the semantics of __proto__ takes more than just saying it is a data > property. Regardless of whether it is ultimately reflected as that or as > an accessor property the semantics of setting it has to be specified in > some manner that likes it to the value that is retrieved by > [[GetInheritance]]. Also, there are already in the spec. at least three > forms of objects (ordinary, exotic symbols, exotic proxies) with different > implementations of [[SetInheritance]] so an internal MOP method has already > proven to be a useful specification device. > Ok. I did a search for [[SetInheritance]] in the Rev13 draft and the only place this method was called was from Reflect.setPrototypeOf and the Proxy "setPrototypeOf" trap default. That's why I thought it could easily be removed. I now see the note that appendix B3.1 (specifying __proto__) is not yet up-to-date. Probably when it's updated, this part of the spec will also call [[SetInheritance]]. > Whether or not it is reflected as a Proxy trap is a separate matter. When > this was discussed recently on es-discuss, the point was made that even if > [[SetInhertance]] intersession by a trap is disallowed (ie, a trap can't > prevent [[SetInheritance]] with the same value from being automatically > invoked on the target) it is still important to get a notification that > [[SetInheritiance]] has occurred. This is similar, to other traps whose > handler behaviors are restricted but were still deemed useful from a > notification perspective. I believe that the conclusion of that discussion > we seemed to have agreement that [[GetInhertiance]] should be handled in > this same manner. > It seems there are two routes we can take a) Introduce a "setPrototypeOf" trap (as currently specified), with the invariant check that the new prototype must match that of the target if setPrototypeOf returns true (a return value of "false" would mean the proxy rejected the prototype change). b) Not treat __proto__ as a magical property on proxies, and get rid of the "setPrototypeOf" trap. This implies that aProxy.__proto__ = val just triggers the "set" trap. This delegates the choice of whether to treat __proto__ as magical or not to every individual proxy handler. Reflect.setPrototypeOf is not essential and simply there to provide a point > of further discussion. I think it is desirable that the Reflect.* interface > be an accurate reflection of the internal MOP. I agree that if we take choice (a) (i.e. introduce a "setPrototypeOf" trap) then we should also have the corresponding Reflect.setPrototypeOf primitive. > Any and all, restrictions that are applied to __prototype__ can also be > applied to Reflect.setPrototypeOf. In fact, the specification of it can be > essentially: > > function setPrototypeOf(target, parent) { > target.__proto__ = parent > }; > Yep. > I'm also of the school that if we are going to accept a mutable > inheritance chain as a standard part of the language then we might as well > embrace it rather than treating is as the black sheep that we try to > pretend isn't really there. > Agreed. Although we should make an effort to make it easy for sandboxes/dialects to remove the feature from the language. That said, I think this issue is orthogonal to our choice of whether or not to expose "setPrototypeOf" as part of the MOP. Even if we do expose it, any sandbox that wants to take away the ability the set the prototype can simply poison Reflect.setPrototypeOf in addition to deleting Object.prototype.__proto__. Cheers, Tom -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121231/e3fe2206/attachment.html>