Closed ljharb closed 1 year ago
One way to do this is to restrict what's in the brackets to be another intrinsic - ie, the spec would take what's inside the brackets, pass that into getIntrinsic, and look up that value.
I assume the getIntrinsic
used would be %getIntrinsic%
, not whichever one may have replaced it in the global?
It also means a layer that adds new intrinsics, potentially including its own well-known symbols, would have to handle the square bracket parsing with the same deferral logic in its replaced getIntrinsic
.
Finally a bit of an edge case, but what if there ever was an intrinsic whose value is a string that is the same as a part of an intrinsic identifier. E.g. if we had %Something.Error%
, could %Something[Error.prototype.name]%
be used as well?
Yes, it'd have to be the original one, and yes, that is a good point that a wrapper would have to handle brackets itself.
E.g. if we had %Something.Error%, could %Something[Error.prototype.name]% be used as well?
One option is "yes", but another, more restrictive option is "no" (ie, if only Symbol.whatever is permitted). Since there's no use case I know of for that to work (template literals provide sufficient dynamism), it seems like the latter is a better choice.
My intention is to resolve this in the following way:
or, the string may use brackets as the final item only, and inside the brackets, the only permitted strings will be Symbol.
concatenated with a valid property name, ie, the well-known symbols table.
When an invalid/unknown string is provided, #6 will decide the semantics.
In addition to well-known symbols, there are two other categories of (serializable) keys that bare idents don’t cover:
I’m guessing there’s no need to provide notation for the first, less sure about the second. Handling the first in realm-uri was the main reason I landed on an @@ grammar there: I was concerned that URL.prototype[Symbol.for("nodejs.util.inspect.custom")]
would look too much like an arbitrary expression. Though I don’t share the distaste for @@, in the absence of the need for for
support, I agree Symbol.foo is probably better.
I don’t think ES defines any (intrinsic) string keys that aren’t valid identifiers (assuming e.g. Object.name["1"]
doesn’t count). In practice, there might not be hosts that do either*, so supporting arbitrary strings may be unnecessary. However it might warrant a note if so given hosts could define initial properties that getIntrinsic wouldn’t have syntax for.
* For web platform objects defined with Web IDL, the grammar for “identifier” almost ensures every string-key property found among the initial objects would also have to match IdentifierName. It departs by allowing hyphens, even as the first character. That seems to have been motivated by a metaprogram-y part of CSSStyleDeclaration’s definition which implicitly declares n interface mixins with a single attribute that has such a name. I can’t find anywhere else that uses hyphens — and in any case neither Chromium nor FF implement the ones I linked to. Both have the generic “named property” getter (→ exotic [[Get]] at instance level) only, not the attributes (→ accessor properties on prototype).
I’m confused; global symbols aren’t intrinsics, and every intrinsic has an identifiername.
If another specification wants to provide intrinsics whose path convention doesn’t match 262, then it’s incumbent on that spec to define how it’s wrapping getIntrinsic.
I’m confused; global symbols aren’t intrinsics
In other threads it seemed you and other folks used the term “intrinsics” both in the realm.[[Intrinsics]]
sense and as a general term for analogous concepts like Web IDL’s “initial objects”. I would have thought the values some spec/host/environment deemed “intrinsic-like” could include any value. The example I gave was a property path for a globally exposed Node built in which a user might expect to be able to retrieve via this API in a Node env. However I wasn’t providing it as an example to demonstrate a need: I was just listing the remaining groups of serializable keys that don’t have (and: may not need) a defined syntax.
and every intrinsic has an identifiername.
(Sticking with the ECMA-262-only sense,) I had thought that only the well-known intrinsics had names, but I might be using the terms wrong. For example I thought %TypedArray% was a “well-known” (and has a name), while %TypedArray.prototype% was not (but was still an intrinsic + could still be expressed using “% notation”). Likewise I figured the %TypedArray%[@@species]
getter was an “intrinsic” too (non-well-known) even though the (spec’s) “% notation” isn’t able to reference it.
If another specification wants to provide intrinsics whose path convention doesn’t match 262, then it’s incumbent on that spec to define how it’s wrapping getIntrinsic.
Ah, that was missing from my picture (though it wouldn’t have been if I’d looked at the spec text first, ooops. I didn’t realize it was already written). The reason I was thinking these things would matter (even if it was just to say concretely “this will not be supported”) is that I imagined the proposal defining hooks of some kind as an extension point for hosts. Now that I realize it’s sufficient for them to just extend the behavior (including, possibly, its “grammar”) without that, I can see that the things I brought up are kinda “non-questions”.
I'm only talking about ecma262's term of "intrinsics", which does not include Symbols in the registry (because none exist in a newly born realm).
I completely agree that %TypedArray.prototype%
is an intrinsic - one where each part of it is an IdentifierName, split by the dots.
I also agree that, say, Array.prototype[Symbol.iterator]
is an intrinsic - one where one of the parts is not an IdentifierName. This issue is asking how we should permit access to that intrinsic in terms of the syntax we accept in the function argument string.
%TypedArray.prototype[Symbol.species]%
is relevant to this issue, because it's a Symbol - but it's also relevant to #4, since it's a getter.
This proposal is not defining any hooks; it's just a function. Hosts will be permitted to provide their own function instead, but ideally they will be normatively constrained so they can't deviate in undesirable ways from the patterns that 262's getIntrinsic
supports.
https://npmjs.com/get-intrinsic does not offer this feature, but this proposal must.
One possibility, that I detest, is:
I do not think we should do this, for a number of reasons:
@@iterator
by itself is a syntax error.We could support:
One way to do this is to restrict what's in the brackets to be another intrinsic - ie, the spec would take what's inside the brackets, pass that into getIntrinsic, and look up that value.
However, since this only has a use case for well-known Symbols, another possibility is that we could only allow brackets to surround "Symbol dot something", where "something" is a well-known symbol name, preceded in the spec with
@@
.