What does this JavaScript error actually mean? I'm not asking about my specific case, just generally how is this error message meant to be understood?

TypeError: 'get' on proxy: property 'items' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '[object Array]' but got '[object Array]')

I don't understand why JavaScript would care what the proxy returns? Why does it matter if its "its actual value" or something else? Isn't what what proxies are (sometimes) used for - returning data in place of the original result?

Additionally - in my specific version of this error message, it appears that the expected type is the same as the returned type so that confuses me even more.

2

There are 2 answers

2
Fabis On BEST ANSWER

Apparently the restriction that causes this error comes from the ECMAScript spec for Proxies, see this section.

[[Get]] for proxy objects enforces the following invariants:

  • The value reported for a property must be the same as the value of the corresponding target object property if the target object property is a non-writable, non-configurable own data property.
  • The value reported for a property must be undefined if the corresponding target object property is a non-configurable own accessor property that has undefined as its [[Get]] attribute.

So if a property of an object is non-writable and non-configurable, the proxy that wraps this object must return the exact same value that the property of the source object holds when the property is read.

In my case the issue was caused by Vue reactifying a non-writable and non-configurable object property and returning the property's value wrapped in another proxy, which broke that rule.

The rule kind of makes sense if you see the proxy as "the same" as the source object. If that source object's property is read-only and not configurable, then any proxy for that object should also not be able to change the value of that property. I'm not sure if I agree, however, because at the end of the day the proxy is not the source object and so I think it should be up to it to decide whether or not to follow the rules of the source object, but maybe I'm missing something.

0
Михаил Кормановский On

Here's a related issue on vue's repo: https://github.com/vuejs/core/issues/3024.

It says that you should use markRaw as a workaround:

Object.defineProperty(outer, "prop", {
      value: markRaw(inner),
      writable: false,
      configurable: false,
});