Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-10-12 Thread #!/JoePea
Gotcha. So basically that tells the consumer "No, you can't use
Proxies". What I want to tell them is "Go ahead, use Proxies to your
heart's content", but I don't want to tell them to write all the
overly-complicated code required for their Proxies to work properly as
soon as I introduce a single private field within my class.


#!/JoePea

On Mon, Jul 27, 2020 at 3:33 PM Jordan Harband  wrote:
>
> oh oops, i meant `if (o !== this)` not `if (o.foo !== this)` :-)
>
> On Mon, Jul 27, 2020 at 3:06 PM #!/JoePea  wrote:
>>
>> > `o.foo(); // works`
>>
>> I think there is something missing from that example as that line
>> throws before it can get to the `new Proxy` line.
>>
>> #!/JoePea
>>
>> On Wed, Jul 15, 2020 at 10:47 PM Jordan Harband  wrote:
>> >
>> > So can:
>> > ```jsx
>> > const o = { foo() { if (o.foo !== this) { throw 'detected'; } } };
>> > o.foo(); // works
>> > new Proxy(o, {}).foo(); // throws
>> > ```
>> >
>> > (as would a class that used a closed-over WeakMap for each "private field")
>> >
>> > Private fields do not introduce any new hazards here.
>> >
>> > On Tue, Jul 14, 2020 at 8:18 PM #!/JoePea  wrote:
>> >>
>> >> >  private members (safely) allow classes with internal slots.
>> >>
>> >> I'd say that they aren't safe, if they can break 3rd-party code on the
>> >> external public side.
>> >>
>> >> #!/JoePea
>> >>
>> >> On Sun, Jul 12, 2020 at 3:09 PM Michael Theriot
>> >>  wrote:
>> >> >
>> >> > I assume OP wants to use proxies and private members together. They are 
>> >> > not designed to be compatible.
>> >> >
>> >> > Proxies and private members are a UX goal primarily for developers. 
>> >> > Proxies easily allow observation of another object or creation of 
>> >> > exotic objects (e.g. Array), and private members (safely) allow classes 
>> >> > with internal slots. Since they cannot be used together the issue 
>> >> > exists, and the hack circumvents this by reimplementing private in a 
>> >> > way that does not require private fields.
>> >> >
>> >> > On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:
>> >> >>
>> >> >> as product-developer, can i ask what ux-objective you ultimately want 
>> >> >> achieved?
>> >> >>
>> >> >> ```js
>> >> >> const sub = new Sub()
>> >> >>
>> >> >> // i'm a noob on proxies. what is this thing (with 
>> >> >> proxied-private-fields) ultimately used for?
>> >> >> const proxy = new Proxy(sub, ...)
>> >> >> ```
>> >> >>
>> >> >> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot 
>> >> >>  wrote:
>> >> >>>
>> >> >>> This does require you to have both the key and the weakmap though, so 
>> >> >>> it actually does succeed in hiding the data so long as the weakmap is 
>> >> >>> out of scope. I guess the issue I can foresee is that the key could 
>> >> >>> be modified after the object is created.
>> >> >>>
>> >> >>> e.g.
>> >> >>> ```js
>> >> >>> var a = new A();
>> >> >>> var key = Object.getOwnPropertySymbols(a)[0];
>> >> >>> delete a[key];
>> >> >>> a.hidden; // throws
>> >> >>> ```
>> >> >>>
>> >> >>> That itself can be guarded by just making the key undeletable. So, I 
>> >> >>> guess this solution could work depending what your goals are?
>> >> >>>
>> >> >>> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot 
>> >> >>>  wrote:
>> >> 
>> >>  It nearly works, but the issue is that the key will be leaked by 
>> >>  `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
>> >> 
>> >>  There have been ideas proposing "private symbols" but I am not 
>> >>  familiar with their issues, and I would guess with Class Fields they 
>> >>  are unlikely to materialize anyway.
>> >> 
>> >>  On Sun, Jul 12, 2020 at 2:19 PM François REMY 
>> >>   wrote:
>> >> >
>> >> > At the risk of pointing out the obvious:
>> >> >
>> >> >
>> >> >
>> >> > ```js
>> >> >
>> >> > const privkey = Symbol();
>> >> >
>> >> > const stores = new WeakMap();
>> >> >
>> >> >
>> >> >
>> >> > class A {
>> >> >
>> >> >   [privkey] = {};
>> >> >
>> >> >   constructor() {
>> >> >
>> >> > const priv = {};
>> >> >
>> >> > priv.hidden = Math.random();
>> >> >
>> >> > stores.set(this[privkey], priv);
>> >> >
>> >> >   }
>> >> >
>> >> >
>> >> >
>> >> >   get hidden() {
>> >> >
>> >> > const priv = stores.get(this[privkey]);
>> >> >
>> >> > return priv.hidden;
>> >> >
>> >> >   }
>> >> >
>> >> > }
>> >> >
>> >> >
>> >> >
>> >> > var as = [
>> >> >
>> >> > new A(),
>> >> >
>> >> > new Proxy(new A(),{}),
>> >> >
>> >> > new Proxy(new A(),{}),
>> >> >
>> >> > ];
>> >> >
>> >> > console.log(as.map(a=>a.hidden));
>> >> >
>> >> > ```
>> >> >
>> >> >
>> >> >
>> >> >
>> >> >
>> >> >
>> >> >
>> >> > From: Michael Theriot
>> >> > Sent: Sunday, July 12, 2020 20:59
>> 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-27 Thread Jordan Harband
oh oops, i meant `if (o !== this)` not `if (o.foo !== this)` :-)

On Mon, Jul 27, 2020 at 3:06 PM #!/JoePea  wrote:

> > `o.foo(); // works`
>
> I think there is something missing from that example as that line
> throws before it can get to the `new Proxy` line.
>
> #!/JoePea
>
> On Wed, Jul 15, 2020 at 10:47 PM Jordan Harband  wrote:
> >
> > So can:
> > ```jsx
> > const o = { foo() { if (o.foo !== this) { throw 'detected'; } } };
> > o.foo(); // works
> > new Proxy(o, {}).foo(); // throws
> > ```
> >
> > (as would a class that used a closed-over WeakMap for each "private
> field")
> >
> > Private fields do not introduce any new hazards here.
> >
> > On Tue, Jul 14, 2020 at 8:18 PM #!/JoePea  wrote:
> >>
> >> >  private members (safely) allow classes with internal slots.
> >>
> >> I'd say that they aren't safe, if they can break 3rd-party code on the
> >> external public side.
> >>
> >> #!/JoePea
> >>
> >> On Sun, Jul 12, 2020 at 3:09 PM Michael Theriot
> >>  wrote:
> >> >
> >> > I assume OP wants to use proxies and private members together. They
> are not designed to be compatible.
> >> >
> >> > Proxies and private members are a UX goal primarily for developers.
> Proxies easily allow observation of another object or creation of exotic
> objects (e.g. Array), and private members (safely) allow classes with
> internal slots. Since they cannot be used together the issue exists, and
> the hack circumvents this by reimplementing private in a way that does not
> require private fields.
> >> >
> >> > On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:
> >> >>
> >> >> as product-developer, can i ask what ux-objective you ultimately
> want achieved?
> >> >>
> >> >> ```js
> >> >> const sub = new Sub()
> >> >>
> >> >> // i'm a noob on proxies. what is this thing (with
> proxied-private-fields) ultimately used for?
> >> >> const proxy = new Proxy(sub, ...)
> >> >> ```
> >> >>
> >> >> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot <
> michael.lee.ther...@gmail.com> wrote:
> >> >>>
> >> >>> This does require you to have both the key and the weakmap though,
> so it actually does succeed in hiding the data so long as the weakmap is
> out of scope. I guess the issue I can foresee is that the key could be
> modified after the object is created.
> >> >>>
> >> >>> e.g.
> >> >>> ```js
> >> >>> var a = new A();
> >> >>> var key = Object.getOwnPropertySymbols(a)[0];
> >> >>> delete a[key];
> >> >>> a.hidden; // throws
> >> >>> ```
> >> >>>
> >> >>> That itself can be guarded by just making the key undeletable. So,
> I guess this solution could work depending what your goals are?
> >> >>>
> >> >>> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot <
> michael.lee.ther...@gmail.com> wrote:
> >> 
> >>  It nearly works, but the issue is that the key will be leaked by
> `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
> >> 
> >>  There have been ideas proposing "private symbols" but I am not
> familiar with their issues, and I would guess with Class Fields they are
> unlikely to materialize anyway.
> >> 
> >>  On Sun, Jul 12, 2020 at 2:19 PM François REMY <
> francois.remy@outlook.com> wrote:
> >> >
> >> > At the risk of pointing out the obvious:
> >> >
> >> >
> >> >
> >> > ```js
> >> >
> >> > const privkey = Symbol();
> >> >
> >> > const stores = new WeakMap();
> >> >
> >> >
> >> >
> >> > class A {
> >> >
> >> >   [privkey] = {};
> >> >
> >> >   constructor() {
> >> >
> >> > const priv = {};
> >> >
> >> > priv.hidden = Math.random();
> >> >
> >> > stores.set(this[privkey], priv);
> >> >
> >> >   }
> >> >
> >> >
> >> >
> >> >   get hidden() {
> >> >
> >> > const priv = stores.get(this[privkey]);
> >> >
> >> > return priv.hidden;
> >> >
> >> >   }
> >> >
> >> > }
> >> >
> >> >
> >> >
> >> > var as = [
> >> >
> >> > new A(),
> >> >
> >> > new Proxy(new A(),{}),
> >> >
> >> > new Proxy(new A(),{}),
> >> >
> >> > ];
> >> >
> >> > console.log(as.map(a=>a.hidden));
> >> >
> >> > ```
> >> >
> >> >
> >> >
> >> >
> >> >
> >> >
> >> >
> >> > From: Michael Theriot
> >> > Sent: Sunday, July 12, 2020 20:59
> >> > To: Michael Haufe
> >> > Cc: es-discuss@mozilla.org
> >> > Subject: Re: Why does a JavaScript class getter for a private
> field fail using a Proxy?
> >> >
> >> >
> >> >
> >> > I experienced this issue prior to this proposal, using weakmaps
> for private access.
> >> >
> >> >
> >> >
> >> > e.g.
> >> >
> >> > ```js
> >> >
> >> > const stores = new WeakMap();
> >> >
> >> > class A {
> >> >   constructor() {
> >> > const priv = {};
> >> > priv.hidden = 0;
> >> > stores.set(this, priv);
> 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-27 Thread #!/JoePea
> `o.foo(); // works`

I think there is something missing from that example as that line
throws before it can get to the `new Proxy` line.

#!/JoePea

On Wed, Jul 15, 2020 at 10:47 PM Jordan Harband  wrote:
>
> So can:
> ```jsx
> const o = { foo() { if (o.foo !== this) { throw 'detected'; } } };
> o.foo(); // works
> new Proxy(o, {}).foo(); // throws
> ```
>
> (as would a class that used a closed-over WeakMap for each "private field")
>
> Private fields do not introduce any new hazards here.
>
> On Tue, Jul 14, 2020 at 8:18 PM #!/JoePea  wrote:
>>
>> >  private members (safely) allow classes with internal slots.
>>
>> I'd say that they aren't safe, if they can break 3rd-party code on the
>> external public side.
>>
>> #!/JoePea
>>
>> On Sun, Jul 12, 2020 at 3:09 PM Michael Theriot
>>  wrote:
>> >
>> > I assume OP wants to use proxies and private members together. They are 
>> > not designed to be compatible.
>> >
>> > Proxies and private members are a UX goal primarily for developers. 
>> > Proxies easily allow observation of another object or creation of exotic 
>> > objects (e.g. Array), and private members (safely) allow classes with 
>> > internal slots. Since they cannot be used together the issue exists, and 
>> > the hack circumvents this by reimplementing private in a way that does not 
>> > require private fields.
>> >
>> > On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:
>> >>
>> >> as product-developer, can i ask what ux-objective you ultimately want 
>> >> achieved?
>> >>
>> >> ```js
>> >> const sub = new Sub()
>> >>
>> >> // i'm a noob on proxies. what is this thing (with 
>> >> proxied-private-fields) ultimately used for?
>> >> const proxy = new Proxy(sub, ...)
>> >> ```
>> >>
>> >> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot 
>> >>  wrote:
>> >>>
>> >>> This does require you to have both the key and the weakmap though, so it 
>> >>> actually does succeed in hiding the data so long as the weakmap is out 
>> >>> of scope. I guess the issue I can foresee is that the key could be 
>> >>> modified after the object is created.
>> >>>
>> >>> e.g.
>> >>> ```js
>> >>> var a = new A();
>> >>> var key = Object.getOwnPropertySymbols(a)[0];
>> >>> delete a[key];
>> >>> a.hidden; // throws
>> >>> ```
>> >>>
>> >>> That itself can be guarded by just making the key undeletable. So, I 
>> >>> guess this solution could work depending what your goals are?
>> >>>
>> >>> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot 
>> >>>  wrote:
>> 
>>  It nearly works, but the issue is that the key will be leaked by 
>>  `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
>> 
>>  There have been ideas proposing "private symbols" but I am not familiar 
>>  with their issues, and I would guess with Class Fields they are 
>>  unlikely to materialize anyway.
>> 
>>  On Sun, Jul 12, 2020 at 2:19 PM François REMY 
>>   wrote:
>> >
>> > At the risk of pointing out the obvious:
>> >
>> >
>> >
>> > ```js
>> >
>> > const privkey = Symbol();
>> >
>> > const stores = new WeakMap();
>> >
>> >
>> >
>> > class A {
>> >
>> >   [privkey] = {};
>> >
>> >   constructor() {
>> >
>> > const priv = {};
>> >
>> > priv.hidden = Math.random();
>> >
>> > stores.set(this[privkey], priv);
>> >
>> >   }
>> >
>> >
>> >
>> >   get hidden() {
>> >
>> > const priv = stores.get(this[privkey]);
>> >
>> > return priv.hidden;
>> >
>> >   }
>> >
>> > }
>> >
>> >
>> >
>> > var as = [
>> >
>> > new A(),
>> >
>> > new Proxy(new A(),{}),
>> >
>> > new Proxy(new A(),{}),
>> >
>> > ];
>> >
>> > console.log(as.map(a=>a.hidden));
>> >
>> > ```
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> > From: Michael Theriot
>> > Sent: Sunday, July 12, 2020 20:59
>> > To: Michael Haufe
>> > Cc: es-discuss@mozilla.org
>> > Subject: Re: Why does a JavaScript class getter for a private field 
>> > fail using a Proxy?
>> >
>> >
>> >
>> > I experienced this issue prior to this proposal, using weakmaps for 
>> > private access.
>> >
>> >
>> >
>> > e.g.
>> >
>> > ```js
>> >
>> > const stores = new WeakMap();
>> >
>> > class A {
>> >   constructor() {
>> > const priv = {};
>> > priv.hidden = 0;
>> > stores.set(this, priv);
>> >   }
>> >
>> >   get hidden() {
>> > const priv = stores.get(this);
>> > return priv.hidden;
>> >   }
>> > }
>> >
>> > const a = new A();
>> > console.log(a.hidden); // 0
>> >
>> > const p = new Proxy(a, {});
>> > console.log(p.hidden); // throws!
>> >
>> > ```
>> >
>> >
>> >
>> > I found a workaround:
>> >
>> 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-15 Thread Jordan Harband
So can:
```jsx
const o = { foo() { if (o.foo !== this) { throw 'detected'; } } };
o.foo(); // works
new Proxy(o, {}).foo(); // throws
```

(as would a class that used a closed-over WeakMap for each "private field")

Private fields do not introduce any new hazards here.

On Tue, Jul 14, 2020 at 8:18 PM #!/JoePea  wrote:

> >  private members (safely) allow classes with internal slots.
>
> I'd say that they aren't safe, if they can break 3rd-party code on the
> external public side.
>
> #!/JoePea
>
> On Sun, Jul 12, 2020 at 3:09 PM Michael Theriot
>  wrote:
> >
> > I assume OP wants to use proxies and private members together. They are
> not designed to be compatible.
> >
> > Proxies and private members are a UX goal primarily for developers.
> Proxies easily allow observation of another object or creation of exotic
> objects (e.g. Array), and private members (safely) allow classes with
> internal slots. Since they cannot be used together the issue exists, and
> the hack circumvents this by reimplementing private in a way that does not
> require private fields.
> >
> > On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:
> >>
> >> as product-developer, can i ask what ux-objective you ultimately want
> achieved?
> >>
> >> ```js
> >> const sub = new Sub()
> >>
> >> // i'm a noob on proxies. what is this thing (with
> proxied-private-fields) ultimately used for?
> >> const proxy = new Proxy(sub, ...)
> >> ```
> >>
> >> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot <
> michael.lee.ther...@gmail.com> wrote:
> >>>
> >>> This does require you to have both the key and the weakmap though, so
> it actually does succeed in hiding the data so long as the weakmap is out
> of scope. I guess the issue I can foresee is that the key could be modified
> after the object is created.
> >>>
> >>> e.g.
> >>> ```js
> >>> var a = new A();
> >>> var key = Object.getOwnPropertySymbols(a)[0];
> >>> delete a[key];
> >>> a.hidden; // throws
> >>> ```
> >>>
> >>> That itself can be guarded by just making the key undeletable. So, I
> guess this solution could work depending what your goals are?
> >>>
> >>> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot <
> michael.lee.ther...@gmail.com> wrote:
> 
>  It nearly works, but the issue is that the key will be leaked by
> `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
> 
>  There have been ideas proposing "private symbols" but I am not
> familiar with their issues, and I would guess with Class Fields they are
> unlikely to materialize anyway.
> 
>  On Sun, Jul 12, 2020 at 2:19 PM François REMY <
> francois.remy@outlook.com> wrote:
> >
> > At the risk of pointing out the obvious:
> >
> >
> >
> > ```js
> >
> > const privkey = Symbol();
> >
> > const stores = new WeakMap();
> >
> >
> >
> > class A {
> >
> >   [privkey] = {};
> >
> >   constructor() {
> >
> > const priv = {};
> >
> > priv.hidden = Math.random();
> >
> > stores.set(this[privkey], priv);
> >
> >   }
> >
> >
> >
> >   get hidden() {
> >
> > const priv = stores.get(this[privkey]);
> >
> > return priv.hidden;
> >
> >   }
> >
> > }
> >
> >
> >
> > var as = [
> >
> > new A(),
> >
> > new Proxy(new A(),{}),
> >
> > new Proxy(new A(),{}),
> >
> > ];
> >
> > console.log(as.map(a=>a.hidden));
> >
> > ```
> >
> >
> >
> >
> >
> >
> >
> > From: Michael Theriot
> > Sent: Sunday, July 12, 2020 20:59
> > To: Michael Haufe
> > Cc: es-discuss@mozilla.org
> > Subject: Re: Why does a JavaScript class getter for a private field
> fail using a Proxy?
> >
> >
> >
> > I experienced this issue prior to this proposal, using weakmaps for
> private access.
> >
> >
> >
> > e.g.
> >
> > ```js
> >
> > const stores = new WeakMap();
> >
> > class A {
> >   constructor() {
> > const priv = {};
> > priv.hidden = 0;
> > stores.set(this, priv);
> >   }
> >
> >   get hidden() {
> > const priv = stores.get(this);
> > return priv.hidden;
> >   }
> > }
> >
> > const a = new A();
> > console.log(a.hidden); // 0
> >
> > const p = new Proxy(a, {});
> > console.log(p.hidden); // throws!
> >
> > ```
> >
> >
> >
> > I found a workaround:
> >
> >
> >
> > ```js
> > const stores = new WeakMap();
> >
> > class A {
> >   constructor() {
> > const priv = {};
> > priv.hidden = 0;
> > stores.set(this, priv);
> >
> > const p = new Proxy(this, {});
> > stores.set(p, priv); // set proxy to map to the same private
> store
> >
> > return p;
> >   }
> >
> >  

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-14 Thread #!/JoePea
>  private members (safely) allow classes with internal slots.

I'd say that they aren't safe, if they can break 3rd-party code on the
external public side.

#!/JoePea

On Sun, Jul 12, 2020 at 3:09 PM Michael Theriot
 wrote:
>
> I assume OP wants to use proxies and private members together. They are not 
> designed to be compatible.
>
> Proxies and private members are a UX goal primarily for developers. Proxies 
> easily allow observation of another object or creation of exotic objects 
> (e.g. Array), and private members (safely) allow classes with internal slots. 
> Since they cannot be used together the issue exists, and the hack circumvents 
> this by reimplementing private in a way that does not require private fields.
>
> On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:
>>
>> as product-developer, can i ask what ux-objective you ultimately want 
>> achieved?
>>
>> ```js
>> const sub = new Sub()
>>
>> // i'm a noob on proxies. what is this thing (with proxied-private-fields) 
>> ultimately used for?
>> const proxy = new Proxy(sub, ...)
>> ```
>>
>> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot 
>>  wrote:
>>>
>>> This does require you to have both the key and the weakmap though, so it 
>>> actually does succeed in hiding the data so long as the weakmap is out of 
>>> scope. I guess the issue I can foresee is that the key could be modified 
>>> after the object is created.
>>>
>>> e.g.
>>> ```js
>>> var a = new A();
>>> var key = Object.getOwnPropertySymbols(a)[0];
>>> delete a[key];
>>> a.hidden; // throws
>>> ```
>>>
>>> That itself can be guarded by just making the key undeletable. So, I guess 
>>> this solution could work depending what your goals are?
>>>
>>> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot 
>>>  wrote:

 It nearly works, but the issue is that the key will be leaked by 
 `Object.getOwnPropertySymbols(new A())`, so it's not truly private.

 There have been ideas proposing "private symbols" but I am not familiar 
 with their issues, and I would guess with Class Fields they are unlikely 
 to materialize anyway.

 On Sun, Jul 12, 2020 at 2:19 PM François REMY 
  wrote:
>
> At the risk of pointing out the obvious:
>
>
>
> ```js
>
> const privkey = Symbol();
>
> const stores = new WeakMap();
>
>
>
> class A {
>
>   [privkey] = {};
>
>   constructor() {
>
> const priv = {};
>
> priv.hidden = Math.random();
>
> stores.set(this[privkey], priv);
>
>   }
>
>
>
>   get hidden() {
>
> const priv = stores.get(this[privkey]);
>
> return priv.hidden;
>
>   }
>
> }
>
>
>
> var as = [
>
> new A(),
>
> new Proxy(new A(),{}),
>
> new Proxy(new A(),{}),
>
> ];
>
> console.log(as.map(a=>a.hidden));
>
> ```
>
>
>
>
>
>
>
> From: Michael Theriot
> Sent: Sunday, July 12, 2020 20:59
> To: Michael Haufe
> Cc: es-discuss@mozilla.org
> Subject: Re: Why does a JavaScript class getter for a private field fail 
> using a Proxy?
>
>
>
> I experienced this issue prior to this proposal, using weakmaps for 
> private access.
>
>
>
> e.g.
>
> ```js
>
> const stores = new WeakMap();
>
> class A {
>   constructor() {
> const priv = {};
> priv.hidden = 0;
> stores.set(this, priv);
>   }
>
>   get hidden() {
> const priv = stores.get(this);
> return priv.hidden;
>   }
> }
>
> const a = new A();
> console.log(a.hidden); // 0
>
> const p = new Proxy(a, {});
> console.log(p.hidden); // throws!
>
> ```
>
>
>
> I found a workaround:
>
>
>
> ```js
> const stores = new WeakMap();
>
> class A {
>   constructor() {
> const priv = {};
> priv.hidden = 0;
> stores.set(this, priv);
>
> const p = new Proxy(this, {});
> stores.set(p, priv); // set proxy to map to the same private store
>
> return p;
>   }
>
>   get hidden() {
> const priv = stores.get(this); // the original instance and proxy 
> both map to the same private store now
> return priv.hidden;
>   }
> }
>
> const a = new A();
>
> console.log(a.hidden);
> ```
>
>
>
> Not ideal, and only works if you provide the proxy in the first place 
> (e.g. making exotic JS objects). But, not necessarily a new issue with 
> proxies, either.
>
>
>
> On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe  
> wrote:
>
> This is a known issue and very painful for me as well. You can see a long 
> ugly discussion here:
>
>
>
> 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-14 Thread #!/JoePea
>TC39 choose (correctly, I think) in favor of secure field privacy. The lesser 
>evil choice.”

The PrivateField tunneling that was talked about in that issue would
not expose any privacy. The fact that external proxies break when
internal code introduces a private field is _actually_ leaking
privacy.

TC39 did not choose in favor of privacy, they chose to leave a feature
out and make private fields less private than they should be.

> With that being said workarounds have already been presented:

Those workaround only work in certain cases, namely when you control
the proxy and then give it to external code, or if you tell all your
users to make sure they write proxy membranes for all your methods
(ouch!).

A true solution would leave all existing code working as-is, and would
never break if internal code introduced a private field.

#!/JoePea

On Sun, Jul 12, 2020 at 3:17 PM Michael Haufe  wrote:
>
> To quote from a short conversation I had with Allen Wirfs-Brock:
>
>
>
> “Proxies have a similar issue WRT the "internal slots" of built-ins. The 
> alternatives were the non-othogonality with Proxy or private fields whose 
> privacy was insecure. TC39 choose (correctly, I think) in favor of secure 
> field privacy. The lesser evil choice.”
>
>
>
> With that being said workarounds have already been presented:
>
>
>
> https://github.com/tc39/proposal-class-fields/issues/106#issuecomment-397484713
>
> https://javascript.info/proxy#private-fields
>
>
>
>
>
>
>
> From: es-discuss  On Behalf Of Michael Theriot
> Sent: Sunday, July 12, 2020 5:10 PM
> To: kai zhu 
> Cc: es-discuss@mozilla.org
> Subject: Re: Why does a JavaScript class getter for a private field fail 
> using a Proxy?
>
>
>
> I assume OP wants to use proxies and private members together. They are not 
> designed to be compatible.
>
>
>
> Proxies and private members are a UX goal primarily for developers. Proxies 
> easily allow observation of another object or creation of exotic objects 
> (e.g. Array), and private members (safely) allow classes with internal slots. 
> Since they cannot be used together the issue exists, and the hack circumvents 
> this by reimplementing private in a way that does not require private fields.
>
>
>
> On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:
>
> as product-developer, can i ask what ux-objective you ultimately want 
> achieved?
>
>
>
> ```js
>
> const sub = new Sub()
>
>
>
> // i'm a noob on proxies. what is this thing (with proxied-private-fields) 
> ultimately used for?
>
> const proxy = new Proxy(sub, ...)
>
> ```
>
>
>
> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot 
>  wrote:
>
> This does require you to have both the key and the weakmap though, so it 
> actually does succeed in hiding the data so long as the weakmap is out of 
> scope. I guess the issue I can foresee is that the key could be modified 
> after the object is created.
>
>
>
> e.g.
>
> ```js
>
> var a = new A();
>
> var key = Object.getOwnPropertySymbols(a)[0];
> delete a[key];
>
> a.hidden; // throws
>
> ```
>
>
>
> That itself can be guarded by just making the key undeletable. So, I guess 
> this solution could work depending what your goals are?
>
>
>
> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot 
>  wrote:
>
> It nearly works, but the issue is that the key will be leaked by 
> `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
>
>
>
> There have been ideas proposing "private symbols" but I am not familiar with 
> their issues, and I would guess with Class Fields they are unlikely to 
> materialize anyway.
>
>
>
> On Sun, Jul 12, 2020 at 2:19 PM François REMY  
> wrote:
>
> At the risk of pointing out the obvious:
>
>
>
> ```js
>
> const privkey = Symbol();
>
> const stores = new WeakMap();
>
>
>
> class A {
>
>   [privkey] = {};
>
>   constructor() {
>
> const priv = {};
>
> priv.hidden = Math.random();
>
> stores.set(this[privkey], priv);
>
>   }
>
>
>
>   get hidden() {
>
> const priv = stores.get(this[privkey]);
>
> return priv.hidden;
>
>   }
>
> }
>
>
>
> var as = [
>
> new A(),
>
> new Proxy(new A(),{}),
>
> new Proxy(new A(),{}),
>
> ];
>
> console.log(as.map(a=>a.hidden));
>
> ```
>
>
>
>
>
>
>
> From: Michael Theriot
> Sent: Sunday, July 12, 2020 20:59
> To: Michael Haufe
> Cc: es-discuss@mozilla.org
> Subject: Re: Why does a JavaScript class getter for a private field fail 
> using a Proxy?
>
>
>
> I experienced this issue prior to this proposal, using weakmaps for private 
> access.
>
>
>
> e.g.
>
> ```js
>
> const stores = new WeakMap();
>
> class A {
>   constructor() {
> const priv = {};
> priv.hidden = 0;
> stores.set(this, priv);
>   }
>
>   get hidden() {
> const priv = stores.get(this);
> return priv.hidden;
>   }
> }
>
> const a = new A();
> console.log(a.hidden); // 0
>
> const p = new Proxy(a, {});
> console.log(p.hidden); // throws!
>
> ```
>
>
>
> I found a workaround:
>
>
>
> ```js
> const stores = new 

RE: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-12 Thread Michael Haufe
To quote from a short conversation I had with Allen Wirfs-Brock:

“Proxies have a similar issue WRT the "internal slots" of built-ins. The 
alternatives were the non-othogonality with Proxy or private fields whose 
privacy was insecure. TC39 choose (correctly, I think) in favor of secure field 
privacy. The lesser evil choice.”

With that being said workarounds have already been presented:

https://github.com/tc39/proposal-class-fields/issues/106#issuecomment-397484713
https://javascript.info/proxy#private-fields



From: es-discuss  On Behalf Of Michael Theriot
Sent: Sunday, July 12, 2020 5:10 PM
To: kai zhu 
Cc: es-discuss@mozilla.org
Subject: Re: Why does a JavaScript class getter for a private field fail using 
a Proxy?

I assume OP wants to use proxies and private members together. They are not 
designed to be compatible.

Proxies and private members are a UX goal primarily for developers. Proxies 
easily allow observation of another object or creation of exotic objects (e.g. 
Array), and private members (safely) allow classes with internal slots. Since 
they cannot be used together the issue exists, and the hack circumvents this by 
reimplementing private in a way that does not require private fields.

On Sun, Jul 12, 2020 at 4:45 PM kai zhu 
mailto:kaizhu...@gmail.com>> wrote:
as product-developer, can i ask what ux-objective you ultimately want achieved?

```js
const sub = new Sub()

// i'm a noob on proxies. what is this thing (with proxied-private-fields) 
ultimately used for?
const proxy = new Proxy(sub, ...)
```

On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot 
mailto:michael.lee.ther...@gmail.com>> wrote:
This does require you to have both the key and the weakmap though, so it 
actually does succeed in hiding the data so long as the weakmap is out of 
scope. I guess the issue I can foresee is that the key could be modified after 
the object is created.

e.g.
```js
var a = new A();
var key = Object.getOwnPropertySymbols(a)[0];
delete a[key];
a.hidden; // throws
```

That itself can be guarded by just making the key undeletable. So, I guess this 
solution could work depending what your goals are?

On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot 
mailto:michael.lee.ther...@gmail.com>> wrote:
It nearly works, but the issue is that the key will be leaked by 
`Object.getOwnPropertySymbols(new A())`, so it's not truly private.

There have been ideas proposing "private symbols" but I am not familiar with 
their issues, and I would guess with Class Fields they are unlikely to 
materialize anyway.

On Sun, Jul 12, 2020 at 2:19 PM François REMY 
mailto:francois.remy@outlook.com>> wrote:
At the risk of pointing out the obvious:

```js
const privkey = Symbol();
const stores = new WeakMap();

class A {
  [privkey] = {};
  constructor() {
const priv = {};
priv.hidden = Math.random();
stores.set(this[privkey], priv);
  }

  get hidden() {
const priv = stores.get(this[privkey]);
return priv.hidden;
  }
}

var as = [
new A(),
new Proxy(new A(),{}),
new Proxy(new A(),{}),
];
console.log(as.map(a=>a.hidden));
```



From: Michael Theriot
Sent: Sunday, July 12, 2020 20:59
To: Michael Haufe
Cc: es-discuss@mozilla.org
Subject: Re: Why does a JavaScript class getter for a private field fail using 
a Proxy?

I experienced this issue prior to this proposal, using weakmaps for private 
access.

e.g.
```js
const stores = new WeakMap();

class A {
  constructor() {
const priv = {};
priv.hidden = 0;
stores.set(this, priv);
  }

  get hidden() {
const priv = stores.get(this);
return priv.hidden;
  }
}

const a = new A();
console.log(a.hidden); // 0

const p = new Proxy(a, {});
console.log(p.hidden); // throws!
```

I found a workaround:

```js
const stores = new WeakMap();

class A {
  constructor() {
const priv = {};
priv.hidden = 0;
stores.set(this, priv);

const p = new Proxy(this, {});
stores.set(p, priv); // set proxy to map to the same private store

return p;
  }

  get hidden() {
const priv = stores.get(this); // the original instance and proxy both map 
to the same private store now
return priv.hidden;
  }
}

const a = new A();

console.log(a.hidden);
```

Not ideal, and only works if you provide the proxy in the first place (e.g. 
making exotic JS objects). But, not necessarily a new issue with proxies, 
either.

On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe 
mailto:t...@thenewobjective.com>> wrote:
This is a known issue and very painful for me as well. You can see a long ugly 
discussion here:



I suggest the following guide to assist you:



Another possible approach is to have your classes extend a proxy:

<>


From: es-discuss 
mailto:es-discuss-boun...@mozilla.org>> On 
Behalf 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-12 Thread Michael Theriot
I assume OP wants to use proxies and private members together. They are not
designed to be compatible.

Proxies and private members are a UX goal primarily for developers. Proxies
easily allow observation of another object or creation of exotic objects
(e.g. Array), and private members (safely) allow classes with internal
slots. Since they cannot be used together the issue exists, and the hack
circumvents this by reimplementing private in a way that does not require
private fields.

On Sun, Jul 12, 2020 at 4:45 PM kai zhu  wrote:

> as product-developer, can i ask what ux-objective you ultimately want
> achieved?
>
> ```js
> const sub = new Sub()
>
> // i'm a noob on proxies. what is this thing (with proxied-private-fields)
> ultimately used for?
> const proxy = new Proxy(sub, ...)
> ```
>
> On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot <
> michael.lee.ther...@gmail.com> wrote:
>
>> This does require you to have both the key and the weakmap though, so it
>> actually does succeed in hiding the data so long as the weakmap is out of
>> scope. I guess the issue I can foresee is that the key could be modified
>> after the object is created.
>>
>> e.g.
>> ```js
>> var a = new A();
>> var key = Object.getOwnPropertySymbols(a)[0];
>> delete a[key];
>> a.hidden; // throws
>> ```
>>
>> That itself can be guarded by just making the key undeletable. So, I
>> guess this solution could work depending what your goals are?
>>
>> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot <
>> michael.lee.ther...@gmail.com> wrote:
>>
>>> It nearly works, but the issue is that the key will be leaked by
>>> `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
>>>
>>> There have been ideas proposing "private symbols" but I am not familiar
>>> with their issues, and I would guess with Class Fields they are unlikely to
>>> materialize anyway.
>>>
>>> On Sun, Jul 12, 2020 at 2:19 PM François REMY <
>>> francois.remy@outlook.com> wrote:
>>>
 At the risk of pointing out the obvious:



 ```js

 const privkey = Symbol();

 const stores = new WeakMap();



 class A {

   [privkey] = {};

   constructor() {

 const priv = {};

 priv.hidden = Math.random();

 stores.set(this[privkey], priv);

   }



   get hidden() {

 const priv = stores.get(this[privkey]);

 return priv.hidden;

   }

 }



 var as = [

 new A(),

 new Proxy(new A(),{}),

 new Proxy(new A(),{}),

 ];

 console.log(as.map(a=>a.hidden));

 ```







 *From: *Michael Theriot 
 *Sent: *Sunday, July 12, 2020 20:59
 *To: *Michael Haufe 
 *Cc: *es-discuss@mozilla.org
 *Subject: *Re: Why does a JavaScript class getter for a private field
 fail using a Proxy?



 I experienced this issue prior to this proposal, using weakmaps for
 private access.



 e.g.

 ```js

 const stores = new WeakMap();

 class A {
   constructor() {
 const priv = {};
 priv.hidden = 0;
 stores.set(this, priv);
   }

   get hidden() {
 const priv = stores.get(this);
 return priv.hidden;
   }
 }

 const a = new A();
 console.log(a.hidden); // 0

 const p = new Proxy(a, {});
 console.log(p.hidden); // throws!

 ```



 I found a workaround:



 ```js
 const stores = new WeakMap();

 class A {
   constructor() {
 const priv = {};
 priv.hidden = 0;
 stores.set(this, priv);

 const p = new Proxy(this, {});
 stores.set(p, priv); // set proxy to map to the same private store

 return p;
   }

   get hidden() {
 const priv = stores.get(this); // the original instance and proxy
 both map to the same private store now
 return priv.hidden;
   }
 }

 const a = new A();

 console.log(a.hidden);
 ```



 Not ideal, and only works if you provide the proxy in the first place
 (e.g. making exotic JS objects). But, not necessarily a new issue with
 proxies, either.



 On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe 
 wrote:

 This is a known issue and very painful for me as well. You can see a
 long ugly discussion here:



 



 I suggest the following guide to assist you:



 



 Another possible approach is to have your classes extend a proxy:



 <
 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-12 Thread kai zhu
as product-developer, can i ask what ux-objective you ultimately want
achieved?

```js
const sub = new Sub()

// i'm a noob on proxies. what is this thing (with proxied-private-fields)
ultimately used for?
const proxy = new Proxy(sub, ...)
```

On Sun, Jul 12, 2020 at 4:34 PM Michael Theriot <
michael.lee.ther...@gmail.com> wrote:

> This does require you to have both the key and the weakmap though, so it
> actually does succeed in hiding the data so long as the weakmap is out of
> scope. I guess the issue I can foresee is that the key could be modified
> after the object is created.
>
> e.g.
> ```js
> var a = new A();
> var key = Object.getOwnPropertySymbols(a)[0];
> delete a[key];
> a.hidden; // throws
> ```
>
> That itself can be guarded by just making the key undeletable. So, I guess
> this solution could work depending what your goals are?
>
> On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot <
> michael.lee.ther...@gmail.com> wrote:
>
>> It nearly works, but the issue is that the key will be leaked by
>> `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
>>
>> There have been ideas proposing "private symbols" but I am not familiar
>> with their issues, and I would guess with Class Fields they are unlikely to
>> materialize anyway.
>>
>> On Sun, Jul 12, 2020 at 2:19 PM François REMY <
>> francois.remy@outlook.com> wrote:
>>
>>> At the risk of pointing out the obvious:
>>>
>>>
>>>
>>> ```js
>>>
>>> const privkey = Symbol();
>>>
>>> const stores = new WeakMap();
>>>
>>>
>>>
>>> class A {
>>>
>>>   [privkey] = {};
>>>
>>>   constructor() {
>>>
>>> const priv = {};
>>>
>>> priv.hidden = Math.random();
>>>
>>> stores.set(this[privkey], priv);
>>>
>>>   }
>>>
>>>
>>>
>>>   get hidden() {
>>>
>>> const priv = stores.get(this[privkey]);
>>>
>>> return priv.hidden;
>>>
>>>   }
>>>
>>> }
>>>
>>>
>>>
>>> var as = [
>>>
>>> new A(),
>>>
>>> new Proxy(new A(),{}),
>>>
>>> new Proxy(new A(),{}),
>>>
>>> ];
>>>
>>> console.log(as.map(a=>a.hidden));
>>>
>>> ```
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> *From: *Michael Theriot 
>>> *Sent: *Sunday, July 12, 2020 20:59
>>> *To: *Michael Haufe 
>>> *Cc: *es-discuss@mozilla.org
>>> *Subject: *Re: Why does a JavaScript class getter for a private field
>>> fail using a Proxy?
>>>
>>>
>>>
>>> I experienced this issue prior to this proposal, using weakmaps for
>>> private access.
>>>
>>>
>>>
>>> e.g.
>>>
>>> ```js
>>>
>>> const stores = new WeakMap();
>>>
>>> class A {
>>>   constructor() {
>>> const priv = {};
>>> priv.hidden = 0;
>>> stores.set(this, priv);
>>>   }
>>>
>>>   get hidden() {
>>> const priv = stores.get(this);
>>> return priv.hidden;
>>>   }
>>> }
>>>
>>> const a = new A();
>>> console.log(a.hidden); // 0
>>>
>>> const p = new Proxy(a, {});
>>> console.log(p.hidden); // throws!
>>>
>>> ```
>>>
>>>
>>>
>>> I found a workaround:
>>>
>>>
>>>
>>> ```js
>>> const stores = new WeakMap();
>>>
>>> class A {
>>>   constructor() {
>>> const priv = {};
>>> priv.hidden = 0;
>>> stores.set(this, priv);
>>>
>>> const p = new Proxy(this, {});
>>> stores.set(p, priv); // set proxy to map to the same private store
>>>
>>> return p;
>>>   }
>>>
>>>   get hidden() {
>>> const priv = stores.get(this); // the original instance and proxy
>>> both map to the same private store now
>>> return priv.hidden;
>>>   }
>>> }
>>>
>>> const a = new A();
>>>
>>> console.log(a.hidden);
>>> ```
>>>
>>>
>>>
>>> Not ideal, and only works if you provide the proxy in the first place
>>> (e.g. making exotic JS objects). But, not necessarily a new issue with
>>> proxies, either.
>>>
>>>
>>>
>>> On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe 
>>> wrote:
>>>
>>> This is a known issue and very painful for me as well. You can see a
>>> long ugly discussion here:
>>>
>>>
>>>
>>> 
>>>
>>>
>>>
>>> I suggest the following guide to assist you:
>>>
>>>
>>>
>>> 
>>>
>>>
>>>
>>> Another possible approach is to have your classes extend a proxy:
>>>
>>>
>>>
>>> <
>>> https://github.com/tc39/proposal-class-fields/issues/106#issuecomment-397484713
>>> >
>>>
>>>
>>>
>>>
>>>
>>> *From:* es-discuss  *On Behalf Of *Laurie
>>> Harper
>>> *Sent:* Friday, June 5, 2020 12:21 AM
>>> *To:* es-discuss@mozilla.org
>>> *Subject:* Why does a JavaScript class getter for a private field fail
>>> using a Proxy?
>>>
>>>
>>>
>>> I can expose private class fields in JavaScript using getters, and those
>>> getters work correctly when invoked on instances of a subclass. However, if
>>> I then wrap the instance with a proxy the getter will throw a type error,
>>> even if the proxy `get` hook uses `Reflect.get()`:
>>>
>>> ```
>>> class Base {
>>> _attrA
>>> #_attrB
>>>
>>> constructor() {
>>> this._attrA = 100
>>> this.#_attrB = 200
>>> }
>>>
>>> get A() { return 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-12 Thread Michael Theriot
This does require you to have both the key and the weakmap though, so it
actually does succeed in hiding the data so long as the weakmap is out of
scope. I guess the issue I can foresee is that the key could be modified
after the object is created.

e.g.
```js
var a = new A();
var key = Object.getOwnPropertySymbols(a)[0];
delete a[key];
a.hidden; // throws
```

That itself can be guarded by just making the key undeletable. So, I guess
this solution could work depending what your goals are?

On Sun, Jul 12, 2020 at 4:21 PM Michael Theriot <
michael.lee.ther...@gmail.com> wrote:

> It nearly works, but the issue is that the key will be leaked by
> `Object.getOwnPropertySymbols(new A())`, so it's not truly private.
>
> There have been ideas proposing "private symbols" but I am not familiar
> with their issues, and I would guess with Class Fields they are unlikely to
> materialize anyway.
>
> On Sun, Jul 12, 2020 at 2:19 PM François REMY <
> francois.remy@outlook.com> wrote:
>
>> At the risk of pointing out the obvious:
>>
>>
>>
>> ```js
>>
>> const privkey = Symbol();
>>
>> const stores = new WeakMap();
>>
>>
>>
>> class A {
>>
>>   [privkey] = {};
>>
>>   constructor() {
>>
>> const priv = {};
>>
>> priv.hidden = Math.random();
>>
>> stores.set(this[privkey], priv);
>>
>>   }
>>
>>
>>
>>   get hidden() {
>>
>> const priv = stores.get(this[privkey]);
>>
>> return priv.hidden;
>>
>>   }
>>
>> }
>>
>>
>>
>> var as = [
>>
>> new A(),
>>
>> new Proxy(new A(),{}),
>>
>> new Proxy(new A(),{}),
>>
>> ];
>>
>> console.log(as.map(a=>a.hidden));
>>
>> ```
>>
>>
>>
>>
>>
>>
>>
>> *From: *Michael Theriot 
>> *Sent: *Sunday, July 12, 2020 20:59
>> *To: *Michael Haufe 
>> *Cc: *es-discuss@mozilla.org
>> *Subject: *Re: Why does a JavaScript class getter for a private field
>> fail using a Proxy?
>>
>>
>>
>> I experienced this issue prior to this proposal, using weakmaps for
>> private access.
>>
>>
>>
>> e.g.
>>
>> ```js
>>
>> const stores = new WeakMap();
>>
>> class A {
>>   constructor() {
>> const priv = {};
>> priv.hidden = 0;
>> stores.set(this, priv);
>>   }
>>
>>   get hidden() {
>> const priv = stores.get(this);
>> return priv.hidden;
>>   }
>> }
>>
>> const a = new A();
>> console.log(a.hidden); // 0
>>
>> const p = new Proxy(a, {});
>> console.log(p.hidden); // throws!
>>
>> ```
>>
>>
>>
>> I found a workaround:
>>
>>
>>
>> ```js
>> const stores = new WeakMap();
>>
>> class A {
>>   constructor() {
>> const priv = {};
>> priv.hidden = 0;
>> stores.set(this, priv);
>>
>> const p = new Proxy(this, {});
>> stores.set(p, priv); // set proxy to map to the same private store
>>
>> return p;
>>   }
>>
>>   get hidden() {
>> const priv = stores.get(this); // the original instance and proxy
>> both map to the same private store now
>> return priv.hidden;
>>   }
>> }
>>
>> const a = new A();
>>
>> console.log(a.hidden);
>> ```
>>
>>
>>
>> Not ideal, and only works if you provide the proxy in the first place
>> (e.g. making exotic JS objects). But, not necessarily a new issue with
>> proxies, either.
>>
>>
>>
>> On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe 
>> wrote:
>>
>> This is a known issue and very painful for me as well. You can see a long
>> ugly discussion here:
>>
>>
>>
>> 
>>
>>
>>
>> I suggest the following guide to assist you:
>>
>>
>>
>> 
>>
>>
>>
>> Another possible approach is to have your classes extend a proxy:
>>
>>
>>
>> <
>> https://github.com/tc39/proposal-class-fields/issues/106#issuecomment-397484713
>> >
>>
>>
>>
>>
>>
>> *From:* es-discuss  *On Behalf Of *Laurie
>> Harper
>> *Sent:* Friday, June 5, 2020 12:21 AM
>> *To:* es-discuss@mozilla.org
>> *Subject:* Why does a JavaScript class getter for a private field fail
>> using a Proxy?
>>
>>
>>
>> I can expose private class fields in JavaScript using getters, and those
>> getters work correctly when invoked on instances of a subclass. However, if
>> I then wrap the instance with a proxy the getter will throw a type error,
>> even if the proxy `get` hook uses `Reflect.get()`:
>>
>> ```
>> class Base {
>> _attrA
>> #_attrB
>>
>> constructor() {
>> this._attrA = 100
>> this.#_attrB = 200
>> }
>>
>> get A() { return this._attrA }
>>
>> get B() { return this.#_attrB }
>>
>> incrA() { this._attrA++ }
>>
>> incrB() { this.#_attrB++ }
>> }
>>
>> class Sub extends Base {}
>>
>> const sub = new Sub()
>>
>> const proxy = new Proxy(sub, {
>> get(target, prop, receiver) {
>> const value = Reflect.get(target, prop, receiver)
>> return typeof value === 'function' ? value.bind(target) : value
>> // (1)
>> }
>> })
>>
>> console.log('sub.A', sub.A) // OK: -> 100
>> console.log('sub.B', sub.B) // OK: -> 200
>> sub.incrA() // OK
>> sub.incrB() // OK
>> 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-12 Thread Michael Theriot
It nearly works, but the issue is that the key will be leaked by
`Object.getOwnPropertySymbols(new A())`, so it's not truly private.

There have been ideas proposing "private symbols" but I am not familiar
with their issues, and I would guess with Class Fields they are unlikely to
materialize anyway.

On Sun, Jul 12, 2020 at 2:19 PM François REMY 
wrote:

> At the risk of pointing out the obvious:
>
>
>
> ```js
>
> const privkey = Symbol();
>
> const stores = new WeakMap();
>
>
>
> class A {
>
>   [privkey] = {};
>
>   constructor() {
>
> const priv = {};
>
> priv.hidden = Math.random();
>
> stores.set(this[privkey], priv);
>
>   }
>
>
>
>   get hidden() {
>
> const priv = stores.get(this[privkey]);
>
> return priv.hidden;
>
>   }
>
> }
>
>
>
> var as = [
>
> new A(),
>
> new Proxy(new A(),{}),
>
> new Proxy(new A(),{}),
>
> ];
>
> console.log(as.map(a=>a.hidden));
>
> ```
>
>
>
>
>
>
>
> *From: *Michael Theriot 
> *Sent: *Sunday, July 12, 2020 20:59
> *To: *Michael Haufe 
> *Cc: *es-discuss@mozilla.org
> *Subject: *Re: Why does a JavaScript class getter for a private field
> fail using a Proxy?
>
>
>
> I experienced this issue prior to this proposal, using weakmaps for
> private access.
>
>
>
> e.g.
>
> ```js
>
> const stores = new WeakMap();
>
> class A {
>   constructor() {
> const priv = {};
> priv.hidden = 0;
> stores.set(this, priv);
>   }
>
>   get hidden() {
> const priv = stores.get(this);
> return priv.hidden;
>   }
> }
>
> const a = new A();
> console.log(a.hidden); // 0
>
> const p = new Proxy(a, {});
> console.log(p.hidden); // throws!
>
> ```
>
>
>
> I found a workaround:
>
>
>
> ```js
> const stores = new WeakMap();
>
> class A {
>   constructor() {
> const priv = {};
> priv.hidden = 0;
> stores.set(this, priv);
>
> const p = new Proxy(this, {});
> stores.set(p, priv); // set proxy to map to the same private store
>
> return p;
>   }
>
>   get hidden() {
> const priv = stores.get(this); // the original instance and proxy both
> map to the same private store now
> return priv.hidden;
>   }
> }
>
> const a = new A();
>
> console.log(a.hidden);
> ```
>
>
>
> Not ideal, and only works if you provide the proxy in the first place
> (e.g. making exotic JS objects). But, not necessarily a new issue with
> proxies, either.
>
>
>
> On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe 
> wrote:
>
> This is a known issue and very painful for me as well. You can see a long
> ugly discussion here:
>
>
>
> 
>
>
>
> I suggest the following guide to assist you:
>
>
>
> 
>
>
>
> Another possible approach is to have your classes extend a proxy:
>
>
>
> <
> https://github.com/tc39/proposal-class-fields/issues/106#issuecomment-397484713
> >
>
>
>
>
>
> *From:* es-discuss  *On Behalf Of *Laurie
> Harper
> *Sent:* Friday, June 5, 2020 12:21 AM
> *To:* es-discuss@mozilla.org
> *Subject:* Why does a JavaScript class getter for a private field fail
> using a Proxy?
>
>
>
> I can expose private class fields in JavaScript using getters, and those
> getters work correctly when invoked on instances of a subclass. However, if
> I then wrap the instance with a proxy the getter will throw a type error,
> even if the proxy `get` hook uses `Reflect.get()`:
>
> ```
> class Base {
> _attrA
> #_attrB
>
> constructor() {
> this._attrA = 100
> this.#_attrB = 200
> }
>
> get A() { return this._attrA }
>
> get B() { return this.#_attrB }
>
> incrA() { this._attrA++ }
>
> incrB() { this.#_attrB++ }
> }
>
> class Sub extends Base {}
>
> const sub = new Sub()
>
> const proxy = new Proxy(sub, {
> get(target, prop, receiver) {
> const value = Reflect.get(target, prop, receiver)
> return typeof value === 'function' ? value.bind(target) : value //
> (1)
> }
> })
>
> console.log('sub.A', sub.A) // OK: -> 100
> console.log('sub.B', sub.B) // OK: -> 200
> sub.incrA() // OK
> sub.incrB() // OK
> console.log('sub.A', sub.A) // OK: -> 101
> console.log('sub.B', sub.B) // OK: -> 201
>
> console.log('proxy.A', proxy.A) // OK: -> 100
> console.log('proxy.B', proxy.B) // TypeError: Cannot read private member
> #_attrB from an object whose class did not declare it
> proxy.incrA() // OK
> proxy.incrB() // OK due to (1)
> console.log('proxy.A', proxy.A) // OK: -> 100
> console.log('proxy.B', proxy.B) // TypeError: Cannot read private member
> #_attrB from an object whose class did not declare it
> ```
>
> The call to `proxy.incrB()` works, because the proxy handler explicitly
> binds function values to `target` on line (1). Without the `bind()` call,
> the `proxy.incrB()` invocation would throw a `TypeError` like the getter
> invocation does. That makes some sense: the result of the call to
> `Reflect.get()` is the 'unbound' function value of the property being
> 

RE: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-12 Thread François REMY
At the risk of pointing out the obvious:

```js
const privkey = Symbol();
const stores = new WeakMap();

class A {
  [privkey] = {};
  constructor() {
const priv = {};
priv.hidden = Math.random();
stores.set(this[privkey], priv);
  }

  get hidden() {
const priv = stores.get(this[privkey]);
return priv.hidden;
  }
}

var as = [
new A(),
new Proxy(new A(),{}),
new Proxy(new A(),{}),
];
console.log(as.map(a=>a.hidden));
```



From: Michael Theriot
Sent: Sunday, July 12, 2020 20:59
To: Michael Haufe
Cc: es-discuss@mozilla.org
Subject: Re: Why does a JavaScript class getter for a private field fail using 
a Proxy?

I experienced this issue prior to this proposal, using weakmaps for private 
access.

e.g.
```js
const stores = new WeakMap();

class A {
  constructor() {
const priv = {};
priv.hidden = 0;
stores.set(this, priv);
  }

  get hidden() {
const priv = stores.get(this);
return priv.hidden;
  }
}

const a = new A();
console.log(a.hidden); // 0

const p = new Proxy(a, {});
console.log(p.hidden); // throws!
```

I found a workaround:

```js
const stores = new WeakMap();

class A {
  constructor() {
const priv = {};
priv.hidden = 0;
stores.set(this, priv);

const p = new Proxy(this, {});
stores.set(p, priv); // set proxy to map to the same private store

return p;
  }

  get hidden() {
const priv = stores.get(this); // the original instance and proxy both map 
to the same private store now
return priv.hidden;
  }
}

const a = new A();

console.log(a.hidden);
```

Not ideal, and only works if you provide the proxy in the first place (e.g. 
making exotic JS objects). But, not necessarily a new issue with proxies, 
either.

On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe 
mailto:t...@thenewobjective.com>> wrote:
This is a known issue and very painful for me as well. You can see a long ugly 
discussion here:



I suggest the following guide to assist you:



Another possible approach is to have your classes extend a proxy:




From: es-discuss 
mailto:es-discuss-boun...@mozilla.org>> On 
Behalf Of Laurie Harper
Sent: Friday, June 5, 2020 12:21 AM
To: es-discuss@mozilla.org
Subject: Why does a JavaScript class getter for a private field fail using a 
Proxy?

I can expose private class fields in JavaScript using getters, and those 
getters work correctly when invoked on instances of a subclass. However, if I 
then wrap the instance with a proxy the getter will throw a type error, even if 
the proxy `get` hook uses `Reflect.get()`:

```
class Base {
_attrA
#_attrB

constructor() {
this._attrA = 100
this.#_attrB = 200
}

get A() { return this._attrA }

get B() { return this.#_attrB }

incrA() { this._attrA++ }

incrB() { this.#_attrB++ }
}

class Sub extends Base {}

const sub = new Sub()

const proxy = new Proxy(sub, {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver)
return typeof value === 'function' ? value.bind(target) : value // (1)
}
})

console.log('sub.A', sub.A) // OK: -> 100
console.log('sub.B', sub.B) // OK: -> 200
sub.incrA() // OK
sub.incrB() // OK
console.log('sub.A', sub.A) // OK: -> 101
console.log('sub.B', sub.B) // OK: -> 201

console.log('proxy.A', proxy.A) // OK: -> 100
console.log('proxy.B', proxy.B) // TypeError: Cannot read private member 
#_attrB from an object whose class did not declare it
proxy.incrA() // OK
proxy.incrB() // OK due to (1)
console.log('proxy.A', proxy.A) // OK: -> 100
console.log('proxy.B', proxy.B) // TypeError: Cannot read private member 
#_attrB from an object whose class did not declare it
```

The call to `proxy.incrB()` works, because the proxy handler explicitly binds 
function values to `target` on line (1). Without the `bind()` call, the 
`proxy.incrB()` invocation would throw a `TypeError` like the getter invocation 
does. That makes some sense: the result of the call to `Reflect.get()` is the 
'unbound' function value of the property being retrieved, which must then be 
bound to `target`; it would make more sense, though, if `this` binding was 
applied by the [[Call]] operation on the result of the [[Get]] operation...

But there is no opportunity to 'bind' a getter before invoking it; as a result, 
a proxied getter ends up receiving the wrong `this` binding, leading to the 
inconsistency.

Is there any way to make this work correctly? The only approach I can think of 
(which I haven't tried) would be to have the `get` hook walk up the prototype 
chain, starting from `target`, calling `getOwnPropertyDescriptor()` and 
checking 

Re: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-07-12 Thread Michael Theriot
I experienced this issue prior to this proposal, using weakmaps for private
access.

e.g.
```js
const stores = new WeakMap();

class A {
  constructor() {
const priv = {};
priv.hidden = 0;
stores.set(this, priv);
  }

  get hidden() {
const priv = stores.get(this);
return priv.hidden;
  }
}

const a = new A();
console.log(a.hidden); // 0

const p = new Proxy(a, {});
console.log(p.hidden); // throws!
```

I found a workaround:

```js
const stores = new WeakMap();

class A {
  constructor() {
const priv = {};
priv.hidden = 0;
stores.set(this, priv);

const p = new Proxy(this, {});
stores.set(p, priv); // set proxy to map to the same private store

return p;
  }

  get hidden() {
const priv = stores.get(this); // the original instance and proxy both
map to the same private store now
return priv.hidden;
  }
}

const a = new A();

console.log(a.hidden);
```

Not ideal, and only works if you provide the proxy in the first place (e.g.
making exotic JS objects). But, not necessarily a new issue with proxies,
either.

On Fri, Jun 5, 2020 at 12:29 AM Michael Haufe 
wrote:

> This is a known issue and very painful for me as well. You can see a long
> ugly discussion here:
>
>
>
> 
>
>
>
> I suggest the following guide to assist you:
>
>
>
> 
>
>
>
> Another possible approach is to have your classes extend a proxy:
>
>
>
> <
> https://github.com/tc39/proposal-class-fields/issues/106#issuecomment-397484713
> >
>
>
>
>
>
> *From:* es-discuss  * On Behalf Of *Laurie
> Harper
> *Sent:* Friday, June 5, 2020 12:21 AM
> *To:* es-discuss@mozilla.org
> *Subject:* Why does a JavaScript class getter for a private field fail
> using a Proxy?
>
>
>
> I can expose private class fields in JavaScript using getters, and those
> getters work correctly when invoked on instances of a subclass. However, if
> I then wrap the instance with a proxy the getter will throw a type error,
> even if the proxy `get` hook uses `Reflect.get()`:
>
> ```
> class Base {
> _attrA
> #_attrB
>
> constructor() {
> this._attrA = 100
> this.#_attrB = 200
> }
>
> get A() { return this._attrA }
>
> get B() { return this.#_attrB }
>
> incrA() { this._attrA++ }
>
> incrB() { this.#_attrB++ }
> }
>
> class Sub extends Base {}
>
> const sub = new Sub()
>
> const proxy = new Proxy(sub, {
> get(target, prop, receiver) {
> const value = Reflect.get(target, prop, receiver)
> return typeof value === 'function' ? value.bind(target) : value //
> (1)
> }
> })
>
> console.log('sub.A', sub.A) // OK: -> 100
> console.log('sub.B', sub.B) // OK: -> 200
> sub.incrA() // OK
> sub.incrB() // OK
> console.log('sub.A', sub.A) // OK: -> 101
> console.log('sub.B', sub.B) // OK: -> 201
>
> console.log('proxy.A', proxy.A) // OK: -> 100
> console.log('proxy.B', proxy.B) // TypeError: Cannot read private member
> #_attrB from an object whose class did not declare it
> proxy.incrA() // OK
> proxy.incrB() // OK due to (1)
> console.log('proxy.A', proxy.A) // OK: -> 100
> console.log('proxy.B', proxy.B) // TypeError: Cannot read private member
> #_attrB from an object whose class did not declare it
> ```
>
> The call to `proxy.incrB()` works, because the proxy handler explicitly
> binds function values to `target` on line (1). Without the `bind()` call,
> the `proxy.incrB()` invocation would throw a `TypeError` like the getter
> invocation does. That makes some sense: the result of the call to
> `Reflect.get()` is the 'unbound' function value of the property being
> retrieved, which must then be bound to `target`; it would make more sense,
> though, if `this` binding was applied by the [[Call]] operation on the
> result of the [[Get]] operation...
>
> But there is no opportunity to 'bind' a getter before invoking it; as a
> result, a proxied getter ends up receiving the wrong `this` binding,
> leading to the inconsistency.
>
> Is there any way to make this work correctly? The only approach I can
> think of (which I haven't tried) would be to have the `get` hook walk up
> the prototype chain, starting from `target`, calling
> `getOwnPropertyDescriptor()` and checking for a getter method, and
> explicitly applying the getter with an adjusted `this` binding. That sounds
> ludicrously cumbersome and brittle...
>
> Is there a better way to get this working correctly?
>
>
>
> --
>
> Laurie
> ___
> 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: Why does a JavaScript class getter for a private field fail using a Proxy?

2020-06-04 Thread Michael Haufe
This is a known issue and very painful for me as well. You can see a long ugly 
discussion here:



I suggest the following guide to assist you:



Another possible approach is to have your classes extend a proxy:




From: es-discuss  On Behalf Of Laurie Harper
Sent: Friday, June 5, 2020 12:21 AM
To: es-discuss@mozilla.org
Subject: Why does a JavaScript class getter for a private field fail using a 
Proxy?

I can expose private class fields in JavaScript using getters, and those 
getters work correctly when invoked on instances of a subclass. However, if I 
then wrap the instance with a proxy the getter will throw a type error, even if 
the proxy `get` hook uses `Reflect.get()`:

```
class Base {
_attrA
#_attrB

constructor() {
this._attrA = 100
this.#_attrB = 200
}

get A() { return this._attrA }

get B() { return this.#_attrB }

incrA() { this._attrA++ }

incrB() { this.#_attrB++ }
}

class Sub extends Base {}

const sub = new Sub()

const proxy = new Proxy(sub, {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver)
return typeof value === 'function' ? value.bind(target) : value // (1)
}
})

console.log('sub.A', sub.A) // OK: -> 100
console.log('sub.B', sub.B) // OK: -> 200
sub.incrA() // OK
sub.incrB() // OK
console.log('sub.A', sub.A) // OK: -> 101
console.log('sub.B', sub.B) // OK: -> 201

console.log('proxy.A', proxy.A) // OK: -> 100
console.log('proxy.B', proxy.B) // TypeError: Cannot read private member 
#_attrB from an object whose class did not declare it
proxy.incrA() // OK
proxy.incrB() // OK due to (1)
console.log('proxy.A', proxy.A) // OK: -> 100
console.log('proxy.B', proxy.B) // TypeError: Cannot read private member 
#_attrB from an object whose class did not declare it
```

The call to `proxy.incrB()` works, because the proxy handler explicitly binds 
function values to `target` on line (1). Without the `bind()` call, the 
`proxy.incrB()` invocation would throw a `TypeError` like the getter invocation 
does. That makes some sense: the result of the call to `Reflect.get()` is the 
'unbound' function value of the property being retrieved, which must then be 
bound to `target`; it would make more sense, though, if `this` binding was 
applied by the [[Call]] operation on the result of the [[Get]] operation...

But there is no opportunity to 'bind' a getter before invoking it; as a result, 
a proxied getter ends up receiving the wrong `this` binding, leading to the 
inconsistency.

Is there any way to make this work correctly? The only approach I can think of 
(which I haven't tried) would be to have the `get` hook walk up the prototype 
chain, starting from `target`, calling `getOwnPropertyDescriptor()` and 
checking for a getter method, and explicitly applying the getter with an 
adjusted `this` binding. That sounds ludicrously cumbersome and brittle...

Is there a better way to get this working correctly?

--
Laurie
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss