Re: Detecting the type of a DOM object
David Bruant wrote: Le 24/06/2012 14:51, Brendan Eich a écrit : David Bruant wrote: Instead of adding a new [[instanceofHint]] internal property, maybe the [[NativeBrand]] could be reused. +1 on that, which suggests [[NativeBrandMatch]] instead of [[InstanceofMatch]]. Your proposal is more general but I think we should extend HasInstance only very concretely, with what's needed for WebIDL, and probably for any such system that reflects nominal types. What form would it take? The constraints of enabling implementations of WebIDL in pure ES6 (which, on the ES side is bound to the goal of getting rid of host objects) seems to force towards a general proposal. One idea: expose [[NativeBrand]] as a private name object available, depending on implementation details, only to privileged code. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
On Monday, June 25, 2012 at 4:28 AM, Brendan Eich wrote: David Bruant wrote: Le 24/06/2012 14:51, Brendan Eich a écrit : David Bruant wrote: Instead of adding a new [[instanceofHint]] internal property, maybe the [[NativeBrand]] could be reused. +1 on that, which suggests [[NativeBrandMatch]] instead of [[InstanceofMatch]]. Your proposal is more general but I think we should extend HasInstance only very concretely, with what's needed for WebIDL, and probably for any such system that reflects nominal types. What form would it take? The constraints of enabling implementations of WebIDL in pure ES6 (which, on the ES side is bound to the goal of getting rid of host objects) seems to force towards a general proposal. One idea: expose [[NativeBrand]] as a private name object available, depending on implementation details, only to privileged code. Can you give an example or scenario in which a given piece of code would be considered privileged? Rick /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
On Mon, Jun 25, 2012 at 9:11 AM, David Bruant bruan...@gmail.com wrote: snip Firefox is partially built in JavaScript. This code is considered privileged (by opposition to website JavaScript). More things can be allowed to this JavaScript code. In case the DOM is built in pure browser JavaScript (as opposed to content JavaScript), having some privileged-specific capabilities (like changing dynamically the [[NativeBrand]]) can be useful. Thank you -- Good to have on record in the thread :) Rick I'm still internally debating whether this particular case would be useful for writing code or whether it would be just a spec toy. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
On Jun 22, 2012, at 11:01 AM, David Bruant wrote: ... There is a potential security issue. From the wiki [1] (in the case where the instance is a proxy trapping on instanceof): Security issue: the handler is given a reference to the function object (the right-hand side of the instanceof operator). This gives the handler the ability to generate new instances of that function. I note that the referenced material[1] is part of the original Proxy proposal and not the current direct proxy proposal. I may be missing something here, but with direct proxies every handler is passed a reference to its target object and hence if the target is a constructable function the handler might generate an instance of it. Given that, I don't see why an instanceof trap exposes any more than any other trap. In my opinion, the issue stands if the choice is to have either the LHS or RHS of instanceof to trap on instanceof. The more general issue isn't about generating new instances, but about an object gaining access to another object it didn't have access to before the instanceof evaluation. Both cases result in a capability leak. To be more precise, currently, when you write a instanceof b, you don't expect either a or b to leak. This property should probably be preserved even with proxies. You are probably correct about the expectation, but it doesn't reflect what is actually specified by ES=5.1. The normal specified implementations of instanceof or any other polymorphic internal methods don't leak (except in ways fundamental to their normal behavior). However, there are no guarantees that host object implementations of those methods won't leak. Similarly, any value that is reified for use by a Proxy handler could be leaked by the handler. Once such values are presented to externally provided code I don't see how you have any assurance that such code won't pass those values on in ways that you didn't anticipate. ... David [1] http://wiki.ecmascript.org/doku.php?id=harmony:proxies#interaction_with_instanceof ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
On Jun 24, 2012, at 5:51 AM, Brendan Eich wrote: David Bruant wrote: Instead of adding a new [[instanceofHint]] internal property, maybe the [[NativeBrand]] could be reused. +1 on that, which suggests [[NativeBrandMatch]] instead of [[InstanceofMatch]]. No, the whole point of transitioning from [[Class]] to [[NativeBrand]] was to ensure that [[NativeBrand]] was a closed ended, non-extensible set of specification internal nominal type tags that are used within the ES specification primarily to specify various legacy behaviors (certain built-in methods only work on specific built-in objects, etc.) Making [[NativeBrand]] extensible would be exactly equivalent to the current [[Class]] and would have the same issues. For example, it conflates default toString behavior with the internal nominal types. Rather than immediately jumping to over loading existing extension points It would be better to first identify and work out in detail all the extension points that we actually need. After we have done this, would be the right time to go back and see if any of them can be merged. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
Le 25/06/2012 17:36, Allen Wirfs-Brock a écrit : On Jun 22, 2012, at 11:01 AM, David Bruant wrote: ... There is a potential security issue. From the wiki [1] (in the case where the instance is a proxy trapping on instanceof): Security issue: the handler is given a reference to the function object (the right-hand side of the instanceof operator). This gives the handler the ability to generate new instances of that function. I note that the referenced material[1] is part of the original Proxy proposal and not the current direct proxy proposal. I may be missing something here, but with direct proxies every handler is passed a reference to its target object and hence if the target is a constructable function the handler might generate an instance of it. Given that, I don't see why an instanceof trap exposes any more than any other trap. The potential leak could arise when you test instanceof (in the naive hasInstance trap case) with something that wasn't created through the constructor, like: mySecretObject instanceof SomePotentiallyUntrustedConstructor And I agree with you, the constructor has full power over instances it generates. The constructor doesn't even need to be a proxy for that. In my opinion, the issue stands if the choice is to have either the LHS or RHS of instanceof to trap on instanceof. The more general issue isn't about generating new instances, but about an object gaining access to another object it didn't have access to before the instanceof evaluation. Both cases result in a capability leak. To be more precise, currently, when you write a instanceof b, you don't expect either a or b to leak. This property should probably be preserved even with proxies. You are probably correct about the expectation, but it doesn't reflect what is actually specified by ES=5.1. Does it matter? [[HasInstance]] is a specification internal mechanism. There is nothing preventing from re-specifying it (like I suggested in my proposal as an example) as long as it keeps backward compatibility. The same probably goes for any internal method. It's actually the last time this can be done, because proxies will expose a lot of the internal machinery to user code. The normal specified implementations of instanceof or any other polymorphic internal methods don't leak (except in ways fundamental to their normal behavior). However, there are no guarantees that host object implementations of those methods won't leak. My understanding of the let's get rid of host objects is to enable having such guarantees. Is getting rid of host objects a goal? By getting rid of, I mean making what used to be host objects at worst as powerful as proxies. Specifically, in my proposal, I have redrawn the interface available to proxies when it comes to reifying instanceof. If host objects weren't more powerful than proxies and my proposal (or any equivalent) were to be accepted, then user code would be guaranteed that host objects won't leak things they're not supposed to. Similarly, any value that is reified for use by a Proxy handler could be leaked by the handler. Once such values are presented to externally provided code I don't see how you have any assurance that such code won't pass those values on in ways that you didn't anticipate. With my proposal, you can check instanceof with an arbitrary untrusted constructor and your objects won't leak (I built it for that purpose). Assuming my proposal is in, could you write a malicious constructor C that acquires a reference to an object o with only the line 'o instanceof C' and no other interaction between o and C? I'm convinced it's not possible, but maybe I'm wrong. This exercice will either point to a defect in my proposal or help understanding it better, both being a step forward :-) David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
Le 25/06/2012 17:49, Allen Wirfs-Brock a écrit : On Jun 24, 2012, at 5:51 AM, Brendan Eich wrote: David Bruant wrote: Instead of adding a new [[instanceofHint]] internal property, maybe the [[NativeBrand]] could be reused. +1 on that, which suggests [[NativeBrandMatch]] instead of [[InstanceofMatch]]. No, the whole point of transitioning from [[Class]] to [[NativeBrand]] was to ensure that [[NativeBrand]] was a closed ended, non-extensible set of specification internal nominal type tags that are used within the ES specification primarily to specify various legacy behaviors (certain built-in methods only work on specific built-in objects, etc.) Making [[NativeBrand]] extensible would be exactly equivalent to the current [[Class]] and would have the same issues. For example, it conflates default toString behavior with the internal nominal types. From the latest draft: 4) If O has a [[NativeBrand]] internal property, let tag be the corresponding value from the Table 27. 5) Else if O is a host object, let tag be an implementation defined string value. This value may not be Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, or String. 6) Else, let tag be the string value Object. Non-spec objects cannot define a [[NativeBrand]], but can have a tag (which should probably be mentionned in Table 9, no?). This sounds very subtle to me. Also, I don't mind if a new [[InstanceOfHint]] property (that can take any value) is added, but the difference between that and leveraging [[NativeBrand]] (so that non-spec objects can take any value with some exceptions) is also very subtle and I am not sure justified. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
On Jun 25, 2012, at 11:10 AM, David Bruant wrote: Le 25/06/2012 17:49, Allen Wirfs-Brock a écrit : On Jun 24, 2012, at 5:51 AM, Brendan Eich wrote: David Bruant wrote: Instead of adding a new [[instanceofHint]] internal property, maybe the [[NativeBrand]] could be reused. +1 on that, which suggests [[NativeBrandMatch]] instead of [[InstanceofMatch]]. No, the whole point of transitioning from [[Class]] to [[NativeBrand]] was to ensure that [[NativeBrand]] was a closed ended, non-extensible set of specification internal nominal type tags that are used within the ES specification primarily to specify various legacy behaviors (certain built-in methods only work on specific built-in objects, etc.) Making [[NativeBrand]] extensible would be exactly equivalent to the current [[Class]] and would have the same issues. For example, it conflates default toString behavior with the internal nominal types. From the latest draft: 4) If O has a [[NativeBrand]] internal property, let tag be the corresponding value from the Table 27. 5) Else if O is a host object, let tag be an implementation defined string value. This value may not be Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, or String. 6) Else, let tag be the string value Object. Non-spec objects cannot define a [[NativeBrand]], but can have a tag (which should probably be mentionned in Table 9, no?). This sounds very subtle to me. This is just a transitional form of the specification of this method and not its final ES6 specification. This version is essentially a refactoring that replaces [[Class]] with [[InternalBrand]] and moves the restriction that had previously applied to [[Class]] string values from the prose of 8.6.2 into this algorithm. The next step is to specify a more explicit extension mechanism. In an early message on the original thread I said I favored making {}.toString extensional via a private named property. I still do, although there are other possible extension mechanism. Also, I don't mind if a new [[InstanceOfHint]] property (that can take any value) is added, but the difference between that and leveraging [[NativeBrand]] (so that non-spec objects can take any value with some exceptions) is also very subtle and I am not sure justified. I really want to be explicit the extension points: 1) Here is how you extend {}.toSting... 2) Here is how you extend the instanceof operator... Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
2012/6/25 Allen Wirfs-Brock al...@wirfs-brock.com On Jun 22, 2012, at 11:01 AM, David Bruant wrote: ... There is a potential security issue. From the wiki [1] (in the case where the instance is a proxy trapping on instanceof): Security issue: the handler is given a reference to the function object (the right-hand side of the instanceof operator). This gives the handler the ability to generate new instances of that function. I note that the referenced material[1] is part of the original Proxy proposal and not the current direct proxy proposal. I may be missing something here, but with direct proxies every handler is passed a reference to its target object and hence if the target is a constructable function the handler might generate an instance of it. Given that, I don't see why an instanceof trap exposes any more than any other trap. I think you may have misunderstood: in terms of the direct proxy API, the issue referred to on the old Proxy API page was about the danger of having |proxy instanceof function| trap as |handler.hasInstance(target, function)|, thus giving the proxy access to the target (irrelevant in this context) _and_ the RHS function object, which would be a new way for values to interact. To be more precise, currently, when you write a instanceof b, you don't expect either a or b to leak. This property should probably be preserved even with proxies. You are probably correct about the expectation, but it doesn't reflect what is actually specified by ES=5.1. The normal specified implementations of instanceof or any other polymorphic internal methods don't leak (except in ways fundamental to their normal behavior). However, there are no guarantees that host object implementations of those methods won't leak. Similarly, any value that is reified for use by a Proxy handler could be leaked by the handler. Once such values are presented to externally provided code I don't see how you have any assurance that such code won't pass those values on in ways that you didn't anticipate. Your point is that any existing host object _could_ already leak the LHS object (as indeed the spec allows). I think David's point is that as long as no platform-provided host object actually _does_ leak the LHS object, then for all practical purposes |instanceof| currently doesn't leak the LHS object. As to my own opinion about this issue: while I agree we don't want |a instanceof b| to give a access to b, I'm less convinced that the opposite leak is all that problematic. If you're given an untrusted function F, how much trust can you place in the outcome of |obj instanceof F| anyway? Even with the [[InstanceofHint]] trickery, the outcome of the test remains untrusted. Granted, an attacker might take you down the wrong branch of an if-test but still can't get at your |obj|. I guess what I want to say is that code that needs a high-fidelity branding mechanism is better off using alternatives (e.g. WeakMap) rather than relying on instanceof. Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
David Bruant wrote: Instead of adding a new [[instanceofHint]] internal property, maybe the [[NativeBrand]] could be reused. +1 on that, which suggests [[NativeBrandMatch]] instead of [[InstanceofMatch]]. Your proposal is more general but I think we should extend HasInstance only very concretely, with what's needed for WebIDL, and probably for any such system that reflects nominal types. Cc'ing Tom in case he missed this thread, including your message to which I am replying here. (Nit: the 'o' in 'of' should be capitalized if we do use the name you suggested.) /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
Le 24/06/2012 14:51, Brendan Eich a écrit : David Bruant wrote: Instead of adding a new [[instanceofHint]] internal property, maybe the [[NativeBrand]] could be reused. +1 on that, which suggests [[NativeBrandMatch]] instead of [[InstanceofMatch]]. Your proposal is more general but I think we should extend HasInstance only very concretely, with what's needed for WebIDL, and probably for any such system that reflects nominal types. What form would it take? The constraints of enabling implementations of WebIDL in pure ES6 (which, on the ES side is bound to the goal of getting rid of host objects) seems to force towards a general proposal. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
I'm going to try to move the discussion of this issue to es-discuss via a separate message as it is mostly about Proxy design. (bcc'ing public-script-coord) the start of this subthread is the following which identifies that historically the [[HasInstance]] extension point has been used (at least conceptually) to provide alternative instanceof semantics. On Jun 21, 2012, at 7:30 AM, Boris Zbarsky wrote: On 6/21/12 4:15 AM, David Bruant wrote: Le 21/06/2012 07:30, Boris Zbarsky a écrit : Alternately, we could try to make instanceof actually work cross-global? +1, but eternal web worry: won't it break the web? It works cross-global for DOM objects in Gecko right now. We're actually deliberately breaking that in the WebIDL bindings at the moment, so the actual web compat breakage for us is in the other direction: as we move to WebIDL with its stricter instanceof sites might break. On Jun 22, 2012, at 8:14 AM, Tom Van Cutsem wrote: 2012/6/22 David Bruant bruan...@gmail.com For the record, rationale for not including a trap for instanceof was described here: http://wiki.ecmascript.org/doku.php?id=harmony:proxies#interaction_with_instanceof We've gone through this in detail before. There even was a strawman, but it got deferred, see http://wiki.ecmascript.org/doku.php?id=strawman:proxy_instanceof From that strawman's feedback section: TC39 November 2010 meeting: after a meeting with the Web IDL editors, agreed that Web IDL should not expose the multiple inheritance. Hence, a custom [[HasInstance]] would not be necessary to wrap these host objects. But the usage from FireFox that was recently identified isn't particularly related to multiple inheritance. There may be other use cases for a custom [[HasInstance]] (outside of Web IDL), but until such cases are identified we agreed not to pursue this strawman in the interest of not further complicating the Proxy API. This needs to be part of what we cover on es-discuss, but my position is that [HasInstance]] is a clearly defined legacy object behavior extension point. If it isn't need it should go away entirely. If it has utility, then it should be part of the proxy handler surface area because that the mechanism for exposing such extension points into ES code. I don't think the new direct proxies API impacts this strawman, so technically I see no reason why proxies can't have a [[HasInstance]] trap if needed. I agree, I don't see that it presents any technical hurdles. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
On 6/22/12 1:12 PM, Brandon Benvie wrote: While the issue identified may not be particularly related to multiple inheritance, the issue in general I think is a looming one in terms of the goal of being able to self-host the DOM in JS. It seems to be becoming more and more common for various kinds of partial interfaces/supplement/implements to be used in newer IDLs and many of those are difficult/impossible to fully represent in JavaScript without a lot of redundancy or backflips. Partial interfaces should be a non-issue. There is no supplement. implements is a bit of a pain, yes. Not just in JavaScript: see the recent thread on public-script-coord about the this-unwrapping behavior of implements -Boris ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
On Jun 22, 2012, at 10:12 AM, Brandon Benvie wrote: While the issue identified may not be particularly related to multiple inheritance, the issue in general I think is a looming one in terms of the goal of being able to self-host the DOM in JS. It seems to be becoming more and more common for various kinds of partial interfaces/supplement/implements to be used in newer IDLs and many of those are difficult/impossible to fully represent in JavaScript without a lot of redundancy or backflips. At the ES language level, the real question is whether the instanceof operator has a single semantics regardless of which objects it is applied to or whether it is an overloadable operator whose meaning is determined by its RHS operand. We should make a clear cut choice between those to alternatives. The legacy ES specification goes in the direction of the overloadable alternative. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
Le 22/06/2012 18:13, Allen Wirfs-Brock a écrit : I'm going to try to move the discussion of this issue to es-discuss via a separate message as it is mostly about Proxy design. (bcc'ing public-script-coord) the start of this subthread is the following which identifies that historically the [[HasInstance]] extension point has been used (at least conceptually) to provide alternative instanceof semantics. I'd like to point out that whether the trap should be on the LHS or RHS of the instanceof expression is a non-trivial choice. If one is chosen over the other, I'd be interested to see this choice being justified. I don't think the new direct proxies API impacts this strawman, so technically I see no reason why proxies can't have a [[HasInstance]] trap if needed. I agree, I don't see that it presents any technical hurdles. There is a potential security issue. From the wiki [1] (in the case where the instance is a proxy trapping on instanceof): Security issue: the handler is given a reference to the function object (the right-hand side of the instanceof operator). This gives the handler the ability to generate new instances of that function. In my opinion, the issue stands if the choice is to have either the LHS or RHS of instanceof to trap on instanceof. The more general issue isn't about generating new instances, but about an object gaining access to another object it didn't have access to before the instanceof evaluation. Both cases result in a capability leak. To be more precise, currently, when you write a instanceof b, you don't expect either a or b to leak. This property should probably be preserved even with proxies. Here is a proposal that enable custom instanceof behavior and doesn't leak either a or b: Any object may (it's not compulsory) have an internal [[instanceofHint]] property (as usual, name isn't set in stone). Any function may have an internal [[instanceofMatch]] method. This method takes a value and returns a boolean. The value will be the [[instanceofHint]] property of an object [[HasInstance]](V) becomes: (Assume F is a Function object which has this [[HasInstance]] property) 1) If V is not an object, return false. 2) If V has an internal [[instanceofHint]] property and F has an internal [[instanceofMatch]] method, return F.[[instanceofMatch]](V.[[instanceofHint]]) 3) else goto step 2 of the ES5.1 [[HasInstance]] algorithm and continue from there. By default, objects do not have an [[instanceofHint]] or [[instanceofMatch]] property, so backward-compatibility is kept for ECMAScript 5 objects. Proxies can have a way to provide both an [[instanceofHint]] and [[instanceofMatch]] internal properties in their handlers to enable custom instanceof behavior. The trap for [[instanceofMatch]] is never handed objects, but only [[instanceofHint]], so as long as these do not leak instances, there cannot be a leak. For WebIDL objects, one way to use this is to say for instance: * Instances of interface A objects have 'A' as [[instanceofHint]] * The [[instanceofMatch]](v) method of constructors is roughly: return true if v refers to one of the constructor subclass and false otherwise. In that case, document instanceof Node would return true (regardless of which global Node or document came from), because document.[[instanceofHint]] would be 'HTMLDocument' and Node.[[instanceofMatch]] would recognize that as a subclass of Node. Instead of adding a new [[instanceofHint]] internal property, maybe the [[NativeBrand]] could be reused. David [1] http://wiki.ecmascript.org/doku.php?id=harmony:proxies#interaction_with_instanceof ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
Allen Wirfs-Brock wrote: I agree, I don't see that it presents any technical hurdles. Agreed. The DOM is alas built from nominal types, so many people believe (x instaceof I) for some WebIDL-declared interface I, even if that I came from another window or frame, should just work. Of course, if the other frame's I.prototype has been extended with a quux property, x won't inherit that property. But that's not how instanceof is used with DOM interfaces, at least. At this point I am in favor of making instanceof more useful for WebIDL consumers, than in being pedantic about prototype chains and multiple global objects. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting the type of a DOM object
While the issue identified may not be particularly related to multiple inheritance, the issue in general I think is a looming one in terms of the goal of being able to self-host the DOM in JS. It seems to be becoming more and more common for various kinds of partial interfaces/supplement/implements to be used in newer IDLs and many of those are difficult/impossible to fully represent in JavaScript without a lot of redundancy or backflips. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss