# The case when it will be useful to have changeable Proxy.target

**URL:** <https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829>\
**Category:** 💡 Ideas\
**Tags:** proxy\
**Created:** [October 23, 2023, 12:09am UTC](https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829 "2023-10-23T00:09:26Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![c-smile](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/c-smile/32/226_2.png) [@c-smile](https://es.discourse.group/u/c-smile)\
**Post date:** [October 23, 2023, 12:09am UTC](https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829/1 "2023-10-23T00:09:26Z")

</div>

There are situations where we need "stable references" to objects. Example [createRef – React](https://react.dev/reference/react/createRef)

That function creates special Reference object that later will receive real object. The caveat is that we always need to access real value with .current property

In fact that functionality may not require anything special. That createRef can be implemented as

```js
function createRef() {
   let p;
   function apply(that) { Proxy.changeTarget(p,that) }
   p = new Proxy(null, {apply});
   return p;
}

```

So we can use proxies also as object references.

```javascript
function Component() {
   const input = createRef(); 
   return <main>
        <label>ref</label> 
        <input type="text" ref={input} /> 
        <button onClick={ () => input.focus() }>focus</button>
   </main>
}

```

here _input_ will receive reference to real DOM element after its creation.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [October 23, 2023, 6:26am UTC](https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829/2 "2023-10-23T06:26:36Z")

</div>

If a proxy could change target that would produce a value that breaks the specified invariants: [ECMAScript® 2024 Language&nbsp;Specification](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-invariants-of-the-essential-internal-methods)

e.g in the React ref example the value goes from being a callable function to a non-callable object.

Another example would be values that go from true to false for `Object.isFrozen`. This would make the language harder to reason about, and potentially invalidate existing checks in code.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [October 23, 2023, 6:33am UTC](https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829/3 "2023-10-23T06:33:35Z")

</div>

One way to achieve something similar in React today:

```javascript
function Component() {
   const [input, setInput] = React.useState();
   return <main>
        <label>ref</label> 
        <input type="text" ref={setInput} /> 
        <button onClick={ () => input.focus() }>focus</button>
   </main>
}

```

Though personally I would stick with `React.useRef` and `ref.current`

---

<div class="post-metadata">

**Author:** ![c-smile](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/c-smile/32/226_2.png) [@c-smile](https://es.discourse.group/u/c-smile)\
**Post date:** [October 23, 2023, 2:24pm UTC](https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829/4 "2023-10-23T14:24:38Z")

</div>

> One way to achieve something similar in React today

Well, in that particular case I've solved this without any state

```javascript
function Component() {
   let input;
   return <main>
        <label>ref</label> 
        <input type="text" var={input} /> 
        <button onClick={ () => input.focus() }>focus</button>
   </main>
}

```

under the hood, in [my JSX implementation](https://sciter.com/forums/topic/reactor-createref-and-refthis-something/) that works as if the following is given:

```javascript
   return <main>
        <label>ref</label> 
        <input type="text" var={ target => input = target } /> 
        <button onClick={ () => input.focus() }>focus</button>
   </main>

```

And the runtime calls functions in @var's upon DOM element construction. This works without any explicit proxies and references.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [October 24, 2023, 6:51pm UTC](https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829/5 "2023-10-24T18:51:01Z")

</div>

You could restrict what changes are allowed to avoid that.

I'm not a fan of OP's suggestion anyways, but for different reasons (namely, performance).

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [October 28, 2023, 10:58am UTC](https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829/6 "2023-10-28T10:58:59Z")

</div>

I'd say that react creates an _unstable_ reference, since it swaps out `.current` behind our backs :-) Or maybe the traditional use case of a react `ref` is that it's a stable but _lazily initialised_ reference.

Regardless, I don't see why you would need `Proxy.changeTarget` for this. You can already implement this today:

```javascript
function createRef() {
  let current = null;
  return new Proxy(newValue => {
    if (typeof newValue === "function") throw new TypeError("Cannot create a mutable ref to a function");
    current = newValue;
  }, {
    getOwnPropertyDescriptor(_, key) {
      return Reflect.getOwnPropertyDescriptor(current, key);
    },
    defineProperty(_, key, descriptor) {
      return Reflect.defineProperty(current, key, descriptor);
    },
    has(_, prop) {
      return Reflect.has(current, prop);
    },
    deleteProperty(_, key) {
      return Reflect.deleteProperty(current, key);
    },
    get(_, key, receiver) {
      return Reflect.get(current, key, receiver);
    },
    set(_, key, value, receiver) {
      return Reflect.set(current, key, value, receiver);
    },
    getPrototypeOf(_) {
      return Reflect.getPrototypeOf(current);
    },
    setPrototypeOf(_, prototype) {
      return Reflect.setPrototypeOf(current, prototype);
    },
    isExtensible(_) {
      return Reflect.isExtensible(current);
    },
    preventExtensions(_) {
      return Reflect.preventExtensions(current);
    },
    ownKeys(_) {
      return Reflect.ownKeys(current);
    },
  });
}

```

(This does probably violate a few proxy invariants, but it's the basic implementation of what you desire).

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [November 8, 2023, 7:41pm UTC](https://es.discourse.group/t/the-case-when-it-will-be-useful-to-have-changeable-proxy-target/1829/7 "2023-11-08T19:41:17Z")

</div>

> [@bergus](#):
>
> (This does probably violate a few proxy invariants, but it's the basic implementation of what you desire).

Wouldn't be too hard to correct, though, and you have two general routes to soundness:

1. Easy: Make `preventExtensions` and `defineProperty` always fail and have `getOwnPropertyDescriptor` only return (possibly failing) writable descriptors. Doing this (and never forwarding them) would ensure it can still change over time.
2. Hard: Disallow target swapping after either `preventExtensions` is called or `defineProperty` is called with a `configurable: false` descriptor. This ensures descriptors always remain consistent for as long as property values can change.

2 also may have other requirements around the backing target and proxy target, but you get the gist.
