On Wed, Dec 4, 2013 at 11:54 AM, Mark Miller <[email protected]> wrote:
> On Wed, Dec 4, 2013 at 6:52 AM, Peter Thiemann
> <[email protected]> wrote:
>>
>>
>> Transparent equality: EQ recursively dereferences proxies to their
>> ultimate non-proxy targets and compares those.
>> Opaque equality: EQ directly compares, i.e., the current state of affairs
>> in JS.
>>
>> Consider
>> var p = new Proxy ( target, handler);
>> The trick is *not* to trap equality, but to let the handler control
>> whether EQ dereferences p to target before comparing pointers. Notice that
>> one handler only controls one step of dereferencing. If target is a proxy,
>> again, then EQ recursively asks that proxy's handler until either a
>> non-proxy object is reached *or* the handler does not request further
>> forwarding.
>> Here is an outline of the proposal:
>> http://proglang.informatik.uni-freiburg.de/projects/JSProxy/proxy.pdf
>>
>> With this design each individual proxy can choose to be transparent or
>> opaque, while guaranteeing that EQ implements a non-trivial equivalence
>> relation - the latter is straightforward to check.
>
>
> Ok good, I see how this provides a meaningful equivalence relation. But I
> don't see how it helps your goal.
>
> a) In order to do a membrane of any sort, including a contract-membrane, you
> need to use the shadow target technique, where the system-recognized target
> for master and slave in your example are distinct shadow targets. And where
> the shared real target is not system recognized, but is only our way of
> describing what the handlers are doing; and thus not available to any system
> enforcement mechanism.

I don't believe that the shadow target technique is in fact required
to implement contracts on top of proxies.

First, it's only required at all if we need to support higher-order
contracts on frozen objects, as your paper discusses.  Frozen objects
are a minority use case in JS today, and it may be that trading off
support for them with other desirable properties of contracts is worth
it.

Second, many uses of frozen objects can be handled without shadow
targets, by simply performing a shallow copy of the object, and
proxying all of the fields.  This works for any object other than
those that have some immutable (ie, nonconfigurable _and_ nonwritable)
and some mutable fields.

Third, the problem with frozen objects, and the reason that shadow
targets are needed at all, is because of precisely the problem that
Andreas and Peter raise in this thread. The invariant enforcement
design that proxies follow, which is exactly the same design we chose
in Racket (see our OOPSLA 2012 paper), is to compare the result of an
intercepted operation with the result of the same operation on the
target. If the two results are not "equal", then an error is
signalled.

In Racket, the sense of "equal" chosen is one that traverses proxies,
and therefore no shadow targets are needed.

Unfortunately, JS provides only one sensible equality operation, which
is `===`, and you and Tom wanted to preserve the invariant that: `x.f
=== x.f` for all immutable data properties on non-host objects. This
would reduce expressiveness without shadow targets, which fortunately
don't cause problems because we've already given up on any equalities
that traverse proxies.

But once we're discussing equality predicates that traverse proxies,
shadow targets are no longer an issue, because such equality
predicates can _fix_ the problem that required shadow targets in the
first place.

>
> You write "If x===y, then uses of x and y *in their common interface* (i.e.,
> in the intersection of their roles) are interchangeable."
>
> b) But this is untrue in your proposal, even if the same system-recognized
> target were somehow used, because the different handlers can perform
> different side effects, including differing side effects on the shared
> target.
>
>
> Let's distinguish two categories of membrane:
>
> x) A general membrane maintains the basic membrane invariant, that there is
> no leakage across the membrane boundary. But invocations that cross the
> membrane can have their meaning changed by the handlers in any way allowed
> by the JS Proxy invariant enforcement mechanism.
>
> y) A guarding membrane is one which either disallows an operation, or
> (identity aside) allows it with the same semantics it would have had in the
> absence of the membrane's interposition.
>
> Given checkably-pure functions (which E and Joe-E have but JS currently does
> not) one can use the general membrane mechanism to build a membrane maker to
> be parameterized by checkably-pure guard predicates, so that it only makes
> guarding membranes. What you (and IIUC Phil and Jeremy) are generally
> seeking are guarding membranes, which would answer issue #b. But in JS (as
> of ES6) these would be implemented by unprivileged user code, and so not
> something that the === implementation could directly recognize. A new
> equivalence operation, whether an EQ-like equivalence predicate or a join,
> could be provided as part of the same package and be in bed with this
> guarding membrane maker.

"Guarding membranes", in your terminology, are just "contracts" (or
"projections" in the terminology of denotational semantics, going back
to the 70s). However, there's no reason that they need the special
level of language support you describe. (Note: I've had trouble
finding any documentation for E's checkably pure functions.) In fact,
I don't think that level of support buys you anything. We already have
the fact that intercepted operations return a semantically-appropriate
value, by the basic semantics.  And even with checkably-pure
functions, using a proxy invokes potentially arbitrary code which you
wouldn't want to do without trusting the code.

In Racket, we've used a proxy system which (a) supports an equality
operation that traverses proxies, and (b) allows proxy handlers to
perform arbitrary operations without any problems that I know of based
on these issues.

Sam
_______________________________________________
dev-tech-js-engine-internals mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals

Reply via email to