Allen Wirfs-Brock (2013-07-30T06:37:55.000Z)
domenic at domenicdenicola.com (2013-08-04T22:43:16.035Z)
On Jul 29, 2013, at 7:04 PM, David Bruant wrote: > 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. > 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. 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 > 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. > Self-hosted code is privileged and may have some power not described by the ES spec (and as far as I know, that's actually the case both for SpiderMonkey and V8 self-hosted code). I'm not talking about existing self-hosted code that uses mechanisms other than Proxy. Some self hosted code might be privileged but that isn't necessarily the case for everything that is self hosted. For example, there is nothing that would need to be particularly privileged about an implementation of Set that is implemented by internally using a Map. You wouldn't even need to use a Proxy for that. > 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. In general, you can't assume that Proxy(x, {}) is substitutable for x. It just doesn't work that way. > 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. 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. > Actually, if the stratification is respected and there is no free bypass, there is no reason to have memory safety issues. Don't know what you mean by free bypass, but it fact that is not a bad description of the default delegation semantics. > 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. ```js 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. > 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. > 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. > 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. Is this a Date according to what you have in mind: ```js let obj = new Date(); obj.__proto__ = null; ``` > 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. > Aside, but related: instead of passing a target (an already built object), it might be an interesting idea to have a Proxy constructor that takes an @@create so that the target passes the @@create-related tests. I don't think is makes any different. That's not the source of the problems. ```js new Proxy(new Array() , { }) ``` has a target that is an exotic array object created via Array[[@@create]] the problem is that the Proxy (and it is what carries identify) is not can not be an exotic array object.