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 <michael.lee.ther...@gmail.com> >>> *Sent: *Sunday, July 12, 2020 20:59 >>> *To: *Michael Haufe <t...@thenewobjective.com> >>> *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 <t...@thenewobjective.com> >>> wrote: >>> >>> This is a known issue and very painful for me as well. You can see a >>> long ugly discussion here: >>> >>> >>> >>> <https://github.com/tc39/proposal-class-fields/issues/106> >>> >>> >>> >>> I suggest the following guide to assist you: >>> >>> >>> >>> <https://javascript.info/proxy#proxy-limitations> >>> >>> >>> >>> 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 <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 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 >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss