The idea is that a class can implement correct-by-construction behavior and validation. In this case not much validation work was saved, but a great deal of work might be saved because a structure of any depth and complexity can be validated this way.
I've used a bikeshed syntax for standard library imports, because in the case where an adversary is present they could easily replace Object.hasOriginalPrototype itself with a different implementation. This proposed convenience allows for tamper-proofing the code even when the code is running in an environment where Object is not itself frozen (as is the case for 99.9% of environments in use today).
I'm not thrilled about private properties for all the reasons that the class-brand-check proposal mentions, but I do like that proposal. It would solve this issue.
Yeah but if I do that I have to give up on anyone ever being able to use my thing with proxies.
I don't feel that class private properties are part of the core language: a proof by contradiction because if they were part of the same core language as proxies the features wouldn't completely break each other.
It's my choice whether or not to ever use class private properties, yet largely not my choice whether anyone will ever try to wrap a proxy around my stuff. My logical conclusion, which mirrors that of others like Lea Verou, is that class private properties are not fully supported and that as a library author I must not use them.
The same argument could be made for proxies. Maybe proxies are not part of the core language because new Proxy(new Map(), {}) doesn't produce a working map object. Or does that mean that Map is not part of the core language. Or to take it even further, you can't put a number inside a WeakSet - does this mean that numbers and WeakSets are not part of the core language?
I'll be honest, I give proxies the same wide avoidance I give class private properties any time I can.
I also was once an absolute banner carrier for Map in data structures. I made it my mission to try to drive adoption of Map. After years and years of it, I give up. I could not in good conscience recommend its use except as a very specific internal performance optimization.
The problems are just so basic: you must give up immutability to use maps in your data for example.
Worse than immutability though, you can't really ever safely get data out of a map. With an object you'd just write obj[key] and you have safe access. If you were to trying to get safe access to read the contents of a map, you'd do something like Map.prototype.get.call(myMap, key), but of course the problem now is the problem we're discussing in the other thread: Map.prototype is a mutable global object and you really have no way of knowing if you're accessing the language's builtin version of get.
o[p] = v is part of the language as is Object.freeze - it's always been perfectly fine for parts of the official language to be incompatible with each other.
Class private fields (not "properties") are far more valuable than Proxies, and anyone using a Proxy outside of a full membrane implementation imo is misusing them, and it's fine that their use cases break. Note as well that private fields aren't the only thing that breaks Proxy usage; a WeakMap keyed by this would be identical (which is how they were spec'd) so it's not even a new capability.
As for "your choice" - any usage of your library that you did not intend should break, loudly. It's far better API design for a library to require users to request a path be opened, than to accidentally create a spacebar heater.
What I don't get about proxies is: even if you're doing a membrane they're still just as broken.
You can only have a membrane if nothing you want to protect behind it uses class private fields or proxies. So if private fields gain wide adoption as a normal part of classes, then membranes would become impossible.
You could argue that this was inevitable, but I don't think it was. All the language needed to do to avoid this pitfall was to make method calling trappable separately from other kinds of property access.
If you did that you would define the method trap so that its second argument, the receiver, was not the proxy itself but the target of the proxy object. Now the existence of a proxy would be transparent, even when making calls to class instances with private fields...