tc39 / proposal-get-intrinsic

EcmaScript language proposal for a way to get intrinsics.
https://tc39.github.io/proposal-get-intrinsic/
MIT License
32 stars 4 forks source link

Extend scope to include discoverability #11

Closed mhofman closed 1 year ago

mhofman commented 2 years ago

As discussed in the TG3 meeting, we'd like the ability to discover all intrinsics in a unified way. Given the relation with getting access to known intrinsics, we'd like to extend the scope of this proposal to include a discoverability feature.

Currently to discover all intrinsics we have to follow all properties descriptors and prototypes from 3 kind of starting points:

The last 2 are problematic as new syntax or APIs may introduce new intrinsics, and require an explicit update of code wishing to discover all intrinsics. Especially problematic for SES / Hardened JS is intrinsics exposed by syntax (undeniable) or updates to existing API calls that are already allow-listed.

If there was a pre-existing unified point through which all intrinsics were discoverable, proposals would no longer have the burden of carefully exposing their otherwise hidden intrinsics in an ad-hoc way.

We believe that discoverability would not be more onerous on implementations than the current scope of a simple access, since implementations would already have to cache all the initial intrinsic values along with their names. It may be worth exploring an API shape that allows the implementation to discover an intrinsic is never reached through this API so that the implementation can collect those intrinsics if otherwise able to.

ljharb commented 2 years ago

As discussed, my primary use case is "get this specific intrinsic", but as long as it doesn't impede that solution advancing, it seems perfectly reasonable to me to also provide an array or iterator over all the available intrinsics.

One possible shape is that getIntrinsic could be iterable; and/or have a keys/values/entries triple like Maps/Sets/Arrays; or have a single own function property attached that returns an iterator.

bathos commented 2 years ago

I’m curious @mhofman whether you would expect this to enumerate host-defined objects addressable via getIntrinsic, too?

I’m hopeful that getIntrinsic would end up extended by hosts as discussed in #5 to allow addressing any* of the Web IDL namespace, interface object, and callback interface objects (plus their member constructs) which are ostensibly created during InitializeHostDefinedRealm.

However I would find it pretty surprising for them to also show up when enumerating**. That makes me wonder whether it’s really is a good idea for getIntrinsics to be host-extended. Maybe it would be better in the long run if it were restricted to real ECMA-262/ECMA-402 intrinsics and a distinct API (ideally one modeled after this one, e.g. getInitialObjects) could be proposed in a WHATWG context for addressing that problem separately.

* “Any” might need to be constrained in some cases for various reasons, though it appears WebGL may finally be killing off the last of the “secret” undiscoverable [LegacyNoInterfaceObject] interfaces.

** Partly just because it seems weird! But another reason is that there are (in some global envs) just so many of them, and in practice, hosts defer the creation of some until they’re first accessed. Enumerating all of the values right off the bat can be surprisingly expensive due to the lazy initialization of some API surfaces in browsers.

ljharb commented 2 years ago

I would expect hosts to be freely able to extend getIntrinsic, and anything accessible from it should show up in the enumeration.

bathos commented 2 years ago

Is there a “...and they should consider doing so,” or just the neutral “it shouldn’t be forbidden”?

If they do extend and follow the same pattern, I think we’d be looking at somewhere in the range of 10,000 entries in a Window env. Unless maybe what’s wanted here is not to enumerate intrinsics/their analogs but rather well-known intrinsics/their analogs? (If the latter, I think prob ~1000).

ljharb commented 2 years ago

I think they should be encouraged to do so. It would include all of them, not just the well-known ones.

Jamesernator commented 2 years ago

** Partly just because it seems weird! But another reason is that there are (in some global envs) just so many of them, and in practice, hosts defer the creation of some until they’re first accessed. Enumerating all of the values right off the bat can be surprisingly expensive due to the lazy initialization of some API surfaces in browsers.

Well enumeration of say .keys() shouldn't cost anything in particular, it would just be a static Array/Iterator of strings essentially. If people are actually enumerating the values, then they probably want to actually do something with those values (i.e. freezing them), in which case loading those objects is neccessary.

ljharb commented 1 year ago

17 is what I've come up with; please review.