Closed acutmore closed 2 years ago
Userland already does create their own predicates using try/catch; so I remain confused why there'd be a web compatibility issue with changing the predicate logic, but not with changing the throw logic.
Predicate functions were talked about in the last Record and Tuple monthly.
To keep the proposal focused the predicates can be pursued in a separate “symbol-predicates” proposals.
Until then @ljharb has kindly created npm packages:
https://npmjs.com/is-registered-symbol https://npmjs.com/is-well-known-symbol https://npmjs.com/intl-fallback-symbol
I'm spinning an issue off from @rricard 's comment here: https://github.com/tc39/proposal-symbols-as-weakmap-keys/pull/23#pullrequestreview-897984341
I remember starting to discuss the different variants of helper functions that could land with this proposal, but I don't recall if we came to a clear answer or not as I failed to take detailed notes.
cc: @ljharb @syg @codehag
Some options for helpers:
A)
WeakMap.isValidKey
et alThere would also be
WeakSet.isValidValid
,WeakRef.isValidTarget
andFinalizationRegistry.isValidTarget
, which would likely all share the same function instance if the logic is the same. This predicate returningtrue
/false
would be a direct indication of if the same value would-not/would throw if attempted to be used with an instance of the class.One issue that has been raised with this helper is that it is likely to 'lock' in the set of valid values; if the only time the logic for this function can change is to encompass new types when they are added to the language, and couldn't change (across versions) for existing types. For example: relaxing the rule to allow 'well-known' symbols in the future. This could impact
Record&Tuple
, if the initial MVP spec for them says they are not validWeakMap
keys, then this could mean they can never be, as the predicate would need to change its result.B)
Object.isUnforgeable
(Doesn't necessarily need to be on
Object
). The key idea here, as I understand it, is to de-couple the predicate from if the value can be used in a weak collection. i.e. it can be used as an indicator but does not necessarily perfectly divide values into the two sets of valid/invalidWeakMap
keys.This could potentially allow the set of valid
WeakMap
keys to change as this predicate itself would always give the same result for a given input across versions. For exampleisUnforgeable(Symbol.iterator)
may always returnfalse
**, but registered symbols may throw when used asWeakMap
keys in one version but then relaxed in future versions. Or forRecord&Tuple
,isUnforgeable(Tuple(Symbol))
could always returntrue
, but maybe this does not guarantee that it is also a validWeakMap
key, relaxing this could then be a future separate proposal.**
`isUnforgeable(Symbol.iterator) === false` may be wrong, it would depend on how we interpret forgeability. ```js // index.js delete Array.prototype[Symbol.unscopables]; delete Symbol.prototype.constructor; delete globalThis.Symbol; // is `@@unscopables` now unreachable? maybe not as [HasBinding](https://tc39.es/ecma262/multipage/executable-code-and-execution-contexts.html#sec-object-environment-records-hasbinding-n) still references it const unscopables = new ShadowRealm().evaluate(`Symbol.unscopables`); // have I re-forged it? ```?) Other options?
Z) No new predicate functions
One option is to not introduce new predicates in the spec itself. This would leave userland to create their own predicates and/or use
try/catch
.