Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

audit builtins to confirm effect of stabilization #6

Open
ljharb opened this issue Feb 20, 2025 · 13 comments
Open

audit builtins to confirm effect of stabilization #6

ljharb opened this issue Feb 20, 2025 · 13 comments

Comments

@ljharb
Copy link
Member

ljharb commented Feb 20, 2025

For example, regexes - this is already a problem with frozen ones (Object.freeze(/a/g).exec('') throws), but is there a reason that stabilized regexes couldn't do something different, like keep the lastIndex in a slot or something?

Also, arrays - say if you have an array subclass (not that we should care about subclasses) that produces a frozen or stabilized array, SubArray.from and SubArray.of will throw, as will subarray.concat, and a number of others.

A stabilized Promise, Map, Set, etc will still be mutable.

All of the implied behaviors might be perfectly fine! but it'd be helpful to have a complete list in case there's an opportunity to do something different.

@gibson042
Copy link
Collaborator

This new level is designed to imply (and be a proper superset of) frozenness, and its additional behavior takes the form of stricter constraints. But all of those behaviors apply to frozenness, and so really aren't even in scope for a strengthening thereof IMO.

If anyone needs something like a frozen or stabilized but still dynamic RegExp instance, then it is incumbent upon them to define the appropriate proxy (or use a library that does so). Fixing that to be more ergonomic would be great, and I'd be willing to help champion that, but this is just not the proposal for it.

@ljharb
Copy link
Member Author

ljharb commented Feb 20, 2025

That's fine, but I'd still like to see a thorough list of builtins and the implications of being stabilized vs frozen.

@gibson042
Copy link
Collaborator

Well, that's easy: because no built-ins are proxies, the only observable difference between using the functionality in this proposal vs. using Object.freeze on them is to address the return-override mistake (preventing such objects from being stamped with private fields) and the assignment-override mistake (allowing objects that inherit from them to create new shadowing properties by assignment)—neither of those differences are specific to particular objects or kinds of objects, and both of them will hopefully be moved from the proposal into more general ECMAScript behavior anyway.

In short, there are no specific implications for built-ins, because this proposal does not interact with exotic behaviors other than those associated with proxies.

@ljharb
Copy link
Member Author

ljharb commented Feb 20, 2025

Fair enough.

I do think that it might actually be in scope of this proposal, however, to consider improvements to behavior vs being frozen, given that there's a web compatibility risk to improvements for frozen objects, but no such risk for stabilized objects. In other words, once this proposal ships, the risk-free window of making such improvements has closed.

@gibson042
Copy link
Collaborator

Sure, do you have any other specific suggestions? I appreciate the ones in this report (relating to RegExp instance lastIndex and Array instance length), I just don't think "frozen but moreso" objects should allow behavior that freezing already rejects (noting that fixing assignment-override does not fall into that category, because it only affects objects further down a prototype chain rather than the frozen object itself).

@mhofman
Copy link
Member

mhofman commented Feb 20, 2025

because no built-ins are proxies, the only observable difference between using the functionality in this proposal vs. using Object.freeze on them is to

Well that's not entirely correct. The idea for stabilize is that any exotic behavior cannot be observable to the JS program. Proxies is just the way to make exotic behavior programmable, and this observable, but some built-ins could make it observable too.

There is one concrete case where stabilize needs to be handled by the built-in: the deferred module namespace object (proposal). Accessing any property of that object will trigger evaluation of user code, something that stabilize doesn't allow. The behavior for the built-in needs to either refuse stabilization until evaluation, or trigger evaluation on stabilization.

I believe no other built-in exposes such observable behavior, however host objects could technically have this behavior too, and would need to be audited and a similar way to handle the case decided if applicable.

@ljharb
Copy link
Member Author

ljharb commented Feb 20, 2025

I don't yet, which is why I was asking for an audit :-)

Certainly if your position is going to be that stablized things shouldn't have any behavior frozen things don't then there's nothing to improve, but I don't think that's a coherent position to hold when the two "mistakes" being fixed by stabilize are both behaviors unchanged by freezing.

@gibson042
Copy link
Collaborator

if your position is going to be that stablized things shouldn't have any behavior frozen things don't

It's not that they don't have any behavior beyond frozenness, it's that any new behavior is stricter/more constrained ("frozen but moreso").

I don't think that's a coherent position to hold when the two "mistakes" being fixed by stabilize are both behaviors unchanged by freezing.

Explaining why it is coherent:

  • proxy non-trapping: The new behavior is stricter than freezing (i.e., inherently in scope).
  • return-override: The new behavior is stricter than freezing; it disallows hidden mutations that freezing still allows (i.e., inherently in scope).
  • assignment-override: Because the new behavior fully prevents any further adjustment to an object, redirecting to it assignment targeting a prototype descendant is not meaningful and leads to bad DX. But this claim also applies to merely-frozen objects and in fact to any non-writable property up a prototype chain, which is why it will hopefully be generalized beyond this proposal.

@ljharb
Copy link
Member Author

ljharb commented Feb 20, 2025

That position basically ensures that any places where freezing makes an object useless in a context, stabilize can't make it less useless, which seems like a huge lost opportunity.

@gibson042
Copy link
Collaborator

That position basically ensures that any places where freezing makes an object useless in a context, stabilize can't make it less useless

💯

which seems like a huge lost opportunity

That's just not the point of this proposal. It would be far worse IMO to have a new integrity level that is more restrictive in some ways and less restrictive in others, rendering it incapable of satisfying the reason for existing in the first place.

But as I mentioned above, I'm happy to work with you or anyone else on addressing such situations (objects made useless by freeze) at their source.

@ljharb
Copy link
Member Author

ljharb commented Feb 20, 2025

Right - but that work is highly likely to have web compat risk for frozen things, and thus be unable to improve anything for freeze.

The point of freezing isn't to make these things useless, it's to prevent the structure from changing, and the point of stabilize as i understand it is to do what freezing "should have done" in the first place - so I'm not sure why it's a requirement that it be more restricting than freezing, as long as it doesn't violate the needs of SES.

@gibson042
Copy link
Collaborator

the point of stabilize as i understand it is to do what freezing "should have done" in the first place

For correcting this misunderstanding, I direct you to the README: «extending the existing system of integrity "levels"… mitigating • The assignment-override-mistake • The return-override-mistake • Proxy reentrancy hazards».

so I'm not sure why it's a requirement that it be more restricting than freezing

That's covered in Background: «These are "levels" because they are currently in a fully-ordered hierarchy: All frozen objects are sealed, and all sealed objects are non-extensible».

@ljharb
Copy link
Member Author

ljharb commented Feb 20, 2025

I understand that that's how this proposal has positioned itself, but that's not the underlying motivation as I understand it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants