emberjs / emberjs/ember.js

[Bug] Wrapping args in a Proxy throws an unintended assertion

Open
#19,130 9 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
22.6k
Forks
4.2k
Avg merge
3d 12h
Merged PRs (30d)
15

Description

### 🐞 Describe the Bug

If you wrap the `args` proxy in another proxy and try to get an undefined property, Ember throws an assertion.

```
Error: Assertion Failed: args proxies do not have real property descriptors, so you should never need to call getOwnPropertyDescriptor yourself. This code exists for enumerability, such as in for-in loops and Object.keys()
```

### 🔬 Minimal Reproduction

The repro app will display errors in the console.
https://github.com/sandydoo/ember-repro-args-proxy

```js
let argsProxy = new Proxy(
this.args,
{
get() {
// Doesn't even matter what you do here.
// You could return a static value and it will still error out .
return Reflect.get(...arguments);
}
}
);

// If args = { definedProp: true }
argsProxy.definedProp // => Returns `true`
argsProxy.undefinedProp // => Throws assertion
```

### 😕 Actual Behavior

It seems that, as part of its implementation, `Proxy` calls `getOwnPropertyDescriptor` on the target object. I don't have control over this 🤷‍♂️. In the case of `args`, `getOwnPropertyDescriptor` throws an error if you try to call it for an undefined prop. The purpose of the assertion seems to be to deter people from using `getOwnPropertyDescriptor` altogether, but since it's necessary for enumeration, it can only throw an error for undefined props.

https://github.com/emberjs/ember.js/blob/e6c38ecbbc1162e600e2058b8fa3bc93993e13aa/packages/%40ember/-internals/glimmer/lib/component-managers/custom.ts#L220-L224

### 🤔 Expected Behavior

I should be able to transparently access properties on `this.args` even via a Proxy.

### 🌍 Environment

- Ember: 3.21.1
- OS: MacOS
- Browser: Firefox, Chrome, and Safari

### 🧠 Thoughts

The assertion strikes me as a bit problematic for a few reasons:

1. It doesn't account for the native behaviour of `Proxy`.
2. Since you can't tell who the callee is and the function is actually necessary in some cases, the assertion is thrown inconsistently. For example, I can call `getOwnPropertyDescriptor` for any _defined_ prop without issues. I'm not sure of what use that would be though...


I would appreciate some feedback on this issue. Are proxies a no-go with args or can we live with the possibility of people calling `getOwnPropertyDescriptor`?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.