David Bruant (2013-07-30T08:25:45.000Z)
2013/7/30 Allen Wirfs-Brock <allen at wirfs-brock.com>

>
> On Jul 29, 2013, at 7:04 PM, David Bruant wrote:
>
> Le 30/07/2013 03:09, Allen Wirfs-Brock a écrit :
>
> On Jul 29, 2013, at 5:11 PM, David Bruant wrote:
>
> Nope.  We would have had the same problems if we had kept [[Class]]. In
> ES<=5.1 [[Class]] is used to conflate situational specific testing for a
> number of independent characteristics of objects.  Some of those
> characteristics can not be transparently prloxied (for example this object
> reference directly refers a special object representation with some
> specific implementation dependent representation of some private state 0)
>
> By "this object reference", are you talking about the "this" keyword?
>
>
> no special "this" here.  I'm just saying that at the implementation level,
> when you are doing  something with an object value what you really have is
> a "reference" (ie a pointer) to a heap allocated data structure.  If the
> implementation code is going to do something that depends on the data
> structures actual memory layout, then you better be sure that you have a
> pointer to the actual data structure you expect.
>
This apply to Date and the "time value", but I fail to see why this doesn't
apply to every object and every property. For instance, every object is
expected to have a [[Prototype]] object (at least in the ES5 era), which
most likelty had a reserved slot in current implementations. Proxies
challenge this, because they don't have a [[Prototype]], so the same sort
of "memory safety hazard" apply for [[Prototype]].
But I'm not too worry about that. I imagine implementors are well-aware of
how deeply proxies are to integrate (retrofit!) in the object model.
They'll figure it out for Date objects as well.



>
> Even then, I wouldn't be sure to understand. Which part of ES5.1 are you
> referring to?
> I believe a code snippet to explain would make things easier to understand.
>
>
> In ES5 some of this is subtle, for example  in the introduction to 15.9.5
> (Properties of Date Prototuype Object) is this paragrpah:
>
> In following descriptions of functions that are properties of the Date
> prototype object, the phrase “this Date object” refers to the object that
> is the this value for the invocation of the function. Unless explicitly
> noted otherwise, none of these functions are generic; a TypeError exception
> is thrown if the this value is not an object for which the value of the
> [[Class]] internal property is "Date". Also, the phrase “this time value”
> refers to the Number value for the time represented by this Date object,
> that is, the value of the [[PrimitiveValue]] internal property of this Date
> object.
>
> and each Date.prototype method starts with a step like:
>
> 1. Let t be this time value.
>
>
> What this is really saying is that this method only works on object
> instances that have the internal layout created by the Date constructor.
>
There is no "really saying". There is saying, there are implementations
that rely on this saying of the spec and since the saying is changing
(admittedly somewhere else in the spec), they'll have to adapt their
implementation to take into account the new sayings.
I'm not sure worrying about implementations is helpful in this debate. This
is a low-level feature. A good test suite applying built-in algorithms to
proxies will go a long way preventing implementation issues.


>
> For a broader discussion of the use of [[Class]] in ES5 see
> https://docs.google.com/document/d/1sSUtri6joyOOh23nVDfMbs1wDS7iDMDUFVVeHeRdSIw/edit?hl=en&authkey=CI-FopgC&pli=1
>
>
Cases are annoyingly numerous, but finite. A test suite can go a long way.
I heard the test suite is moving to Github :-) Only missing is an extensive
doc of the test framework.


> Also, I fail to understand the difference between "if O is an exotic X
> object" and "if O.[[Class]] === X".
>
> There really isn't much.  But getting rid of [[Class]] enables us to
> separate the previously conflated characteristics.
>
> When you test for "if O is an exotic array object", what characteristic
> are you testing for, then?
> This still feels like branding to me.
>
>
> It is exactly branding, but branding for the specific characteristics that
> are defined ES6 clause 8.4.2.  It doesn't include other things that
> [[Class]] was sometimes used for.
>
If the intent behind branding is "internal memory layout", I argue that
this is implementation details leaking into abstraction and that it's a bad
idea especially as it serves no purpose other than memory safety issues
that *might* happen in the transition era between the "before proxy" world
and the "after proxy" world.


>
> So self-hosted code can distinguish an actual array from a proxy, that's
> not an issue.
> Non-privileged code being able to distinguish an array and a proxy for an
> array is more worrisome.
>
>
> I go the other way, in general there should be nothing special about
>  "self-hosting code".  Perhaps the phrase is even misleading. What I'm
> really saying that there should be no particular reason that anything other
> than the most primitive elements of the the ES built-ins can't be expressed
> in ES code.
>
> A proxy with an Array as its target is not an Array.  Whether such an
> object is substitutable for an Array instance is high dependent on the
> details of its handler and other aspects of its implementation.   Also
> please see
> http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api which
> address related issues.
>
This is not enough.
this-binding ("proxy.getMonth()" when the target is a Date) is only half of
the story. The other half remains unadressed
("Date.prototype.getMonth.call(proxy)"). Exotic objects aren't always used
as "this" value. This is exactly Tom's feedback actually.
We need the same solution for both cases (this and non-this usage of
methods).


>
> The (granted implicit) model of "a proxy for exotic object X is seen by
> all algorithms as an exotic object X" feels simpler even if it means that a
> proxy might not act as an internal algorithm expects.
>
> memory safety hazard.  Every place that checks for "is O an exotic X
> object" would have to have a subsequent "is O a Proxy whose target is an
> exotic X" and take different code paths.  If you screw it up, you may have
> memory safety issues.
>
> That's an implementation hazard; not sure what your point is here.
>
>
> The major of such test in the spec. are abstracting over such
> implementation hazards.  That's why they are there.
>
Let's let implementors deal with implementation issues. Let's just make
sure the spec isn't impossible or too high barrier to implement. A test
suite will do the rest. Let's care only for tests that make sense when
authoring.
Implementors are free to dive in here to say I'm wrong and why.



> Most of the other uses are simply for backwards compatibility with spec.
> legacy usages.
>


>
> Note that the design of proxies (can only be new objects, are limited to
> an immutable {target, handler} data structure, stratified API, etc.) go a
> long way in preventing memory safety issues. It sounds reasonable to think
> that implementors will do the necessary rest of work to prevent these
> issues in already implemented algorithms.
>
>
> No, the design actually creates potential safety issues that must be
> carefully guarded against.  For example, the default delegation semantics
> for [[Invoke]]  (it would be the same if [[Get]]/[[Ca]] is used) calls a
> method on the target object with the proxy object as its this value. If the
> target object is exotic or has implementation specific private state (eg,
> [[DateValue]])  the this value (the Proxy) is the wrong kind of object for
> the method to operate upon.  Any implementation level optimization must
> include some sort of guard.
>
Again, this is an implementation concern.
The implementors needs you describe are in the way of authoring (based on
the feedback brought to the list).



>
> In any case, regardless of how many tests a proxy passes, it has always a
> way  to wrongly behave after having passed the test.
>
> The key things are hard dependencies between native code built-in methods
> that expect specific fixed object layouts and the actual instances of those
> objects.
>
> I don't think you're answering my point.
> All tests that methods can pass are pre-conditions.
> If a proxy can pass the test, it can fake it and then behave mistakenly.
> If a proxy can't pass the test, then user-land code can distinguish an
> object from its target.
>
> Here is a simple way Proxies fail your expectations.
>
> let brandRegistry = new WeakSet();
> class Branded {
>    [@@create]() {
>        let obj = super();
>        brandRegistry.add(obj);
>        return obj
>    }
>    doSomething() {
>        if (! Branded.isBranded(this)) throw TypeError("wrong kind of
> object");
>        /...
>     }
>    static isBranded(obj) {
>       return brandRegistry.has(obj)
>     }
> }
>
> let obj = new Branded;
> let pObj = new Proxy (obj, {P });
>
> Branded.isBranded (obj);//true
> Branded.isBranded(pObj); //false
>
> obj.doSomething();  //returns
> pObj.doSomething();  //throws
>
>
> None of the has anything to do with the presence of absence of the ES<=5.1
> [[Class]] internal property.   Instead it is much more fundamental to the
> semantics of Proxy.
>
A target and a proxy have a different object reference. If the difference
can be kept to that, transparent membranes can be implemented, even your
Branded class.
Any code can expect objects with 2 identities to behave differently anyway.



> Something has to be given up. And giving up on indistinguishability would
> defeat the purpose of proxies (and the expectation as feedback on Tom's
> library suggests).
>
>
> You suggestion is?  My point is ES internal branding, whether you call it
> "check for exotic XXX object", "check for the[[XXX]] internal data
> property" or check if [[Class]] == "Array" h does not work with the Direct
> Proxy default handler semantics.
>
Is there a handler semantics with which it can fully work? That's all is
needed.



>
> * Array.isArray
>
> We've discussed the meaning of this in the past and have agreed that it
> should be considered a test for exotic array-ness and in particular the
> length invariant. A Proxy whose target is an exotic array may or may not
> qualify.
>
> I don't really understand what you're testing here to checking the length
> invariant.
>
> It's an implementation internal test.  It is what it means to be "an
> exotic array object". See 8.4.2 of the current ES6 draft for the complete
> specification of what it means to be an "exotic array object"
>
> Can a proxy be written to pass this test?
>
> no, not with portable ES code.  The logic is within Array.isArray, not
> within the object it is applied to.
>
> If some code contains an Array.isArray test, it will behave differently if
> running against a membrane or normal objects. I don't think that's
> desirable.
> For membranes to be transparent, a proxy must be able to behave the
> *exact* same way its target would. Clearly if the logic of some built-in is
> within the built-in not within the object it is applied to, this is plain
> impossible.
>
> It depends upon the type of handler you use for the Proxy's that are form
> your membrane.  The default delegating handler behavior isn't what you
> want. But a ForwardingHanlder should work for you.  At least that's what
> MarkM and TomVC tell me.
>
After Tom initial post on this thread?
Apparently not based on feedback Tom brought to the list. He had to patch
the built-ins for cases where the argument of a built-in is an exotic
object of a given sort.



>
> It's worth noting that I hit upon these issues because users of my
> harmony-reflect shim, which are using direct proxies today in ES5, have
> reported them (see [1],[2]). This adds some evidence that users expect the
> above built-ins to behave transparently w.r.t. proxies for their use cases.
> My library patches some of these built-ins to recognize my own emulated
> proxies, but this is just an ad hoc solution. ES6 users will obviously not
> be able to do this.
>
> They may expect this, but I don't see what generalizations we can make.
>  Whether a proxy over a built-in is behaviorally substitutable for the
> built-in completely dependent upon the the definition of the specific proxy.
>
> Again, this seems to suggest that a proxy could pretend to be a Date to
> one algorithm, an Array to another and a RegExp to another. I'm not sure
> what good comes out of that.
>
> What do you mean to "be a Date".
>
> I wrote "pretend to be a Date". That's at least to the algorithms testing,
> no matter how they do it.
>
>
> My question still stands.  What do you mean when you say "x is a Date".
>  What characteristics of Date are you actually trying to test.
>
oh ok. Then the important part of my sentence is "to one algorithm" (that
implicitly repeats to the other part listed exotic object types). I don't
care about the exact definition used in the built-in algorithms. It just
doesn't feel clean if an object can impersonate a Date (whatever definition
is used) in a built-in algorithm and a RegExp (whatever definition is used)
in another built-in algorithm.
Maybe I just need to get over this point. That's not the major concern here.



> Is this a Date according to what you have in mind:
>
> let obj = new Date();
> obj.__proto__ = null;
>
The definition used in most spec algorithms is "has a this time value", so
I guess this passes.



>
>
> The ES6 spec. defines Dateness very specifically.  It is an ordinary
> object (ie, not a Proxy) that has a [[DateValue]] internal data property
> that can be recognized as such by an implementation.  The only way the ES6
> spec. provides for creating such an object is via the Date[[@@create]]
> method defined in 15.9.3.5 of the current draft.  This method is inherited
> by subclass constructors so  instances of subclasses of the Date
> constructor, by default, also will pass the Dateness test.
>
> Same problem than above about membrane transparency.
>
> This one I have specifically discussed with Tom and Mark.  It depends upon
> using the right kind of handlers for you membrane.
>
This thread feedback brings new data and it seems that the current handler
offering isn't enough (and I understand can't be).

David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130730/4eee2012/attachment-0001.html>
domenic at domenicdenicola.com (2013-08-04T22:47:20.568Z)
2013/7/30 Allen Wirfs-Brock <allen at wirfs-brock.com>

> no special "this" here.  I'm just saying that at the implementation level,
> when you are doing  something with an object value what you really have is
> a "reference" (ie a pointer) to a heap allocated data structure.  If the
> implementation code is going to do something that depends on the data
> structures actual memory layout, then you better be sure that you have a
> pointer to the actual data structure you expect.

This apply to Date and the "time value", but I fail to see why this doesn't
apply to every object and every property. For instance, every object is
expected to have a [[Prototype]] object (at least in the ES5 era), which
most likelty had a reserved slot in current implementations. Proxies
challenge this, because they don't have a [[Prototype]], so the same sort
of "memory safety hazard" apply for [[Prototype]].
But I'm not too worry about that. I imagine implementors are well-aware of
how deeply proxies are to integrate (retrofit!) in the object model.
They'll figure it out for Date objects as well.

> What this is really saying is that this method only works on object
> instances that have the internal layout created by the Date constructor.

There is no "really saying". There is saying, there are implementations
that rely on this saying of the spec and since the saying is changing
(admittedly somewhere else in the spec), they'll have to adapt their
implementation to take into account the new sayings.
I'm not sure worrying about implementations is helpful in this debate. This
is a low-level feature. A good test suite applying built-in algorithms to
proxies will go a long way preventing implementation issues.


> For a broader discussion of the use of [[Class]] in ES5 see
> https://docs.google.com/document/d/1sSUtri6joyOOh23nVDfMbs1wDS7iDMDUFVVeHeRdSIw/edit?hl=en&authkey=CI-FopgC&pli=1

Cases are annoyingly numerous, but finite. A test suite can go a long way.
I heard the test suite is moving to Github :-) Only missing is an extensive
doc of the test framework.


> It is exactly branding, but branding for the specific characteristics that
> are defined ES6 clause 8.4.2.  It doesn't include other things that
> [[Class]] was sometimes used for.

If the intent behind branding is "internal memory layout", I argue that
this is implementation details leaking into abstraction and that it's a bad
idea especially as it serves no purpose other than memory safety issues
that *might* happen in the transition era between the "before proxy" world
and the "after proxy" world.


> A proxy with an Array as its target is not an Array.  Whether such an
> object is substitutable for an Array instance is high dependent on the
> details of its handler and other aspects of its implementation.   Also
> please see
> http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api which
> address related issues.

This is not enough.
this-binding ("proxy.getMonth()" when the target is a Date) is only half of
the story. The other half remains unadressed
("Date.prototype.getMonth.call(proxy)"). Exotic objects aren't always used
as "this" value. This is exactly Tom's feedback actually.
We need the same solution for both cases (this and non-this usage of
methods).

> The major of such test in the spec. are abstracting over such
> implementation hazards.  That's why they are there.

Let's let implementors deal with implementation issues. Let's just make
sure the spec isn't impossible or too high barrier to implement. A test
suite will do the rest. Let's care only for tests that make sense when
authoring.
Implementors are free to dive in here to say I'm wrong and why.

> No, the design actually creates potential safety issues that must be
> carefully guarded against.  For example, the default delegation semantics
> for [[Invoke]]  (it would be the same if [[Get]]/[[Ca]] is used) calls a
> method on the target object with the proxy object as its this value. If the
> target object is exotic or has implementation specific private state (eg,
> [[DateValue]])  the this value (the Proxy) is the wrong kind of object for
> the method to operate upon.  Any implementation level optimization must
> include some sort of guard.

Again, this is an implementation concern.
The implementors needs you describe are in the way of authoring (based on
the feedback brought to the list).

> Here is a simple way Proxies fail your expectations.
>
> ...
>
> None of the has anything to do with the presence of absence of the ES<=5.1
> [[Class]] internal property.   Instead it is much more fundamental to the
> semantics of Proxy.

A target and a proxy have a different object reference. If the difference
can be kept to that, transparent membranes can be implemented, even your
Branded class.
Any code can expect objects with 2 identities to behave differently anyway.



> You suggestion is?  My point is ES internal branding, whether you call it
> "check for exotic XXX object", "check for the[[XXX]] internal data
> property" or check if [[Class]] == "Array" h does not work with the Direct
> Proxy default handler semantics.
>

Is there a handler semantics with which it can fully work? That's all is
needed.

> It depends upon the type of handler you use for the Proxy's that are form
> your membrane.  The default delegating handler behavior isn't what you
> want. But a ForwardingHanlder should work for you.  At least that's what
> MarkM and TomVC tell me.

After Tom initial post on this thread?
Apparently not based on feedback Tom brought to the list. He had to patch
the built-ins for cases where the argument of a built-in is an exotic
object of a given sort.

> My question still stands.  What do you mean when you say "x is a Date".
>  What characteristics of Date are you actually trying to test.

oh ok. Then the important part of my sentence is "to one algorithm" (that
implicitly repeats to the other part listed exotic object types). I don't
care about the exact definition used in the built-in algorithms. It just
doesn't feel clean if an object can impersonate a Date (whatever definition
is used) in a built-in algorithm and a RegExp (whatever definition is used)
in another built-in algorithm.
Maybe I just need to get over this point. That's not the major concern here.



> Is this a Date according to what you have in mind:
>
> ```js
> let obj = new Date();
> obj.__proto__ = null;
> ```

The definition used in most spec algorithms is "has a this time value", so
I guess this passes.

> This one I have specifically discussed with Tom and Mark.  It depends upon
> using the right kind of handlers for you membrane.

This thread feedback brings new data and it seems that the current handler
offering isn't enough (and I understand can't be).