Skip to content

Conversation

@mcmire
Copy link
Contributor

@mcmire mcmire commented Feb 7, 2023

When creating a proxy for an instance of a class, ensure that if a method forwarded to the instance can access private fields within that class. For instance:

class Foo {
  #qux;

  bar() {
    this.#qux = true;
    return this.#baz();
  }

  #baz() {
    return [this.#qux, 42];
  }
}

const foo = new Foo();
const proxy = createSwappableProxy(foo);
proxy.bar();

As it stands, this produces the TypeError:

Cannot write private member #qux to an object whose class did not declare it

If we call this.#baz() before we set #qux, then we get:

Receiver must be an instance of class Foo

We get this error because proxy.bar returns a function that is bound to the proxy object and not our Foo object. Therefore, if we are know we are trying to access a method on Foo we need to get the proxy to return a wrapper function which ensures that when the method is called, it is done so with our Foo instance as this and not the proxy object. This is explained here in the MDN docs:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#no_private_property_forwarding


Fixes #2.

When creating a proxy for an instance of a class, ensure that if a
method forwarded to the instance can access private fields within that
class. For instance:

``` javascript
class Foo {
  #qux;

  bar() {
    this.#qux = true;
    return this.#baz();
  }

  #baz() {
    return [this.#qux, 42];
  }
}

const foo = new Foo();
const proxy = createSwappableProxy(foo);
proxy.bar();
```

As it stands, this produces the TypeError:

    Cannot write private member #qux to an object whose class did not declare it

If we call `this.#baz()` before we set `#qux`, then we get:

    Receiver must be an instance of class Foo

We get this error because `proxy.bar` returns a function that is bound
to the proxy object and not our Foo object. Therefore, if we are know we
are trying to access a method on Foo we need to get the proxy to return
a wrapper function which ensures that when the method is called, it is
done so with our Foo instance as `this` and not the proxy object. This
is explained here in the MDN docs:
<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#no_private_property_forwarding>
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@mcmire mcmire merged commit 1375ccf into master Feb 8, 2023
@mcmire mcmire deleted the support-private-fields branch February 8, 2023 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support instances of classes with private fields

3 participants