Closed mathiasbynens closed 3 years ago
As far as I understand it doesn't and shouldn't, and any code running before you grab globalThis.getIntrinsic
can replace it, which would actually be necessary for any trusted shim that wants to be complete. For example the SES shim would replace getIntrinsic
to prevent access to the untamed Function
constructor or eval
.
So then, what's the point?
You want to call Array.prototype.map(), but you realize that the map function may have been tampered with on Array.prototype. So you call globalThis.getIntrinsic to get the original map function, but that too may have been tampered with. What has been achieved?
The point is that you only have to cache one function instead of N.
The goal is not to protect against first-run code; that’s impossible and must remain so. It’s to protect against later-run code.
Ah, it clicked.
I wasn't thinking about locally caching the globalThis.getIntrinsic
. So, the point of this proposal is to easily provide a way to locally store a snapshot of the current state of things. And the primary benefits of doing this is:
The point is that you only have to cache one function instead of N.
The goal is not to protect against first-run code; that’s impossible and must remain so. It’s to protect against later-run code.
I see. This sounds worth documenting in an FAQ or so :)
The intention was that this was apparent from the narrative in the readme:
The typical approach for package authors to author their code in a way that is robust against later modification is to "cache" - to store a copy in a closed-over lexical variable - the functions they'll need in their package. Note that borrowing a prototype method in this way requires use of .call to set the receiver (the "this" value), so to be robust against that as well it will need to "call-bind" the methods:
Due to code splitting and lazy loading, often these packages will not all be evaluated at the same time, which breaks the "first-run" expectation established above. To minimize the chance of this being a problem, they will often use a common "shared" package to hold all the intrinsics.
This means that whichever shim is evaluated first will also cause get-intrinsic to evaluate first, providing safe, robust access to intrinsics for all other shims, even ones loaded after the environment has been changed.
Shims/polyfills that added new methods would of course need to also wrap/replace the getIntrinsic function so that it also provided the new methods; "lockdown" libraries like SES would similarly need to wrap/replace the getIntrinsic function so it provided whatever forms of these methods it desired.
Understanding the problem space is a bit of a precondition, and my hope was that the full readme text covered that - happy to review a PR that clarifies further.
I'm going to close this as answered, but would love a PR that clarifies the readme - perhaps due to the curse of knowledge, it's as clear as I can personally make it already.
How does this proposal prevent overwriting
globalThis.getIntrinsic
itself? The current draft spec text doesn’t seem to address this. Should it?