Aren’t membranes incompatible with private data via WeakMaps?

# Axel Rauschmayer (9 years ago)

Take, for example, the following class, which uses WeakMaps for its private data:

let _counter = new WeakMap();
let _action = new WeakMap();
class Countdown {
    constructor(counter, action) {
        _counter.set(this, counter);
        _action.set(this, action);
    }
    dec() {
        let counter = _counter.get(this);
        if (counter < 1) return;
        counter--;
        _counter.set(this, counter);
        if (counter === 0) {
            _action.get(this)();
        }
    }
}

If you wrap an instance of Countdown with a revocable Proxy (e.g. when it is returned by a method inside a membrane) that resets its private state, because its this changes.

Right? If yes then I’d expect that to cause problems for code that uses WeakMaps for private data.

# Mark S. Miller (9 years ago)

Answering the question in the subject line, no. The key is the difference between a standalone proxy and a membrane. With a membrane, the key is that the:

  • Countdown class
  • Countdown.prototype
  • Countdown.prototype.dec
  • instances of the Countdown class
  • the WeakMaps used by the Countdown class to store it private state (_counter, _action)

are all on one side of the membrane. As is conventional, let's call that the wet side, and the other side the dry side. Say both a Countdown instance c and the WeakMap _action get passed through the membrane. Let's name the corresponding dry proxies dry_c and dry_action. If, on the dry side, someone does

dry_action.get(dry_c)

then this would trap on dry_action, passing dry_c back through the membrane, resulting in the dry_action handler performing, on the wet side

const r = _action.get(c)

The wet result, r, of this invocation would get passed back through the membrane, leading to the original expression returning dry_r.

Alternatively, let's say that someone on the dry side does

dry_c.dec()

This traps on dry_c, which looks up c's inherited "dec" method, passes that back through the membrane, resulting in a dry_dec proxy for that method. When that is invoked with dry_c as its this, it traps, invoking the wet dec method with c as its this.

Conclusion: it all works fine.

# Axel Rauschmayer (9 years ago)

Thanks! I forgot about unwrapping.