eslint-plugin-ember icon indicating copy to clipboard operation
eslint-plugin-ember copied to clipboard

New Rule: `no-receivers-on-reflect`

Open runspired opened this issue 4 years ago • 0 comments

When using Reflect in the handler for a Proxy, one might choose to use a receiver. Most commonly this happens by default when using rest params. For instance, take the following simple proxy that expects to be proxying to a Model.

class Model {
  @tracked name = 'John';
}
class DangerousProxyImpl {
  constructor(model) {
    return new Proxy(this, {
      get(t, ...args) {
        return Reflect.get(model, ...args);
      },
    });
  }
}

In this case, if an instance of DangerousProxyImpl is supplied to a template, a cache entry will be generated with the proxy instance as a key for any tracked properties that are accessed, as the receiver arg will be the proxy instance and Reflect will set that to be the this context. @tracked utilizes the this context to lookup it's past values in the cache, this lookup will fail to see any changes and instead constantly return the first-rendered value.

As there is no clear solution to this issue within the tracking source-code, I suggest we lint against setting the receiver arg for proxies when using Reflect. For instance, the following code would not exhibit the mentioned bug:

class Model {
  @tracked name = 'John';
}
class SafeProxyImpl {
  constructor(model) {
    return new Proxy(this, {
      get(t, key) {
        return Reflect.get(model, key);
      },
    });
  }
}

runspired avatar Oct 05 '21 21:10 runspired