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

Alternative solution: Identity Symbols #22

Open
hax opened this issue Jan 14, 2022 · 12 comments
Open

Alternative solution: Identity Symbols #22

hax opened this issue Jan 14, 2022 · 12 comments

Comments

@hax
Copy link
Member

hax commented Jan 14, 2022

As #21 discussion, symbol as weakmap key have some arguments on registered symbols, both sides seems have good reasons, maybe we should find some tradeoffs which could satisfy both. I think the root cause of the issues is "symbol as weakmap keys" is too general, as I understand, the main use case is sharable identity, which do not need to be such general. Instead, we could introduce a much limited API:

  • Symbol.of(object) create the identity symbol for the object
  • get Symbol.prototype.object return the object of the identity symbol (return undefined for non-identity symbols)

Usage:

const obj = {}
const sym = Symbol.of(obj)
assert(symbol.object === obj)

Identity symbols (special symbol which ref to the object) would be somewhat like registered symbols (special symbol which ref to the string), so I expect it won't have much troubles to implement.

Note, such API is similar to Object.createSharableIdentity() idea except it use symbol for identity instead of frozen empty object.

@acutmore
Copy link
Contributor

acutmore commented Jan 14, 2022

Similar discussion here: tc39/proposal-record-tuple#273

EDIT: summary of other thread. If Symbol.prototype.object worked cross-ream that would break ShadowRealm isolation. If Symbol.prototype.object was per-realm that creates realm-specific state which was one of the objections to Box.

@acutmore
Copy link
Contributor

One pattern that the weakMap approach enables is 'swappable objects'.

For example #[symbol] can be passed between shadowRealms. But each realm has its own weakMap which maps the symbol to the appropriate object for that realm.

@hax
Copy link
Member Author

hax commented Jan 14, 2022

@acutmore What is "realm-specific state" means? I suppose it should throw TypeError or just return undefined if cross-realm.

@acutmore
Copy link
Contributor

Example of a function having 'realm specific state':

const iFrameRealm = getIframeRealm();

const for1 = globalThis.Symbol.for;
const for2 = iFrameRealm.globalThis.Symbol.for;

const o = {};
for1(o) === for1(o); // the state of for1 is consistent with itself
for1(o) !== for2(o); //  'for' from a different realm has a different internal state

@ljharb
Copy link
Member

ljharb commented Jan 14, 2022

If it doesn’t work cross-realm, then it’s realm-specific, and that’s not something the language does. Template objects are the only example I’m aware of.

@acutmore
Copy link
Contributor

and Template objects are not technically realm-specific. They are tied to the 'parse node'.

function tag(arr) { return arr; }

function f() { return        tag``   ; }
function g() { return eval(' tag`` '); }

assert(f() === f());
assert(g() !== g());

@hax
Copy link
Member Author

hax commented Jan 14, 2022

@acutmore Symbol.of(object) would behave like Symbol.for, always return same symbol value even cross-realm. But Symbol.prototype.object may throw cross-realm.

If it's an iframeRealm and u already have the right to access iframeRealm.globalThis.Symbol, I suppose it could get the object cross-realm. If the code do not have the right to access the other realm due to isolation, it throws. It's a security constraint, I don't treat it as realm-specific.

@ljharb said "any realm has the power to unwrap any realm's Box", I think it could be "any realm has the power to unwrap any realm's Box if it not violate the security isolation".

If we require "any realm has the power to unwrap any realm's Box in any case", it just contradict with the security requirement, so the only solution would be "symbol as weakmap key", as it just transfer the "realm-specific" to userland. And if we also require not differentiate symbols, maybe we have to introduce a new primitive type (for example Identity) for weakmap key. 😅

Another compromise solution is:

Introduce Symbol.identity() to create identity symbols, use Symbol.prototype.isIdentity() to check it, and only allow identity symbols as the weakmap key. It still differentiate the symbols, but at least it have much clear surface API and semantic for the programmers.

@ljharb
Copy link
Member

ljharb commented Jan 14, 2022

There is no consensus on that security isolation being a viable constraint.

There continues to be no consensus that a subset of symbols being weakmap keys is acceptable.

@mhofman
Copy link
Member

mhofman commented Jan 14, 2022

It seems you're reinventing ObjectPlaceholder and going through all the motions the champion group went through.

Identity symbols (special symbol which ref to the object) would be somewhat like registered symbols (special symbol which ref to the string), so I expect it won't have much troubles to implement.

Taking a step back, how does this solve one of the objection that all symbols be treated the same when adding to WeakMap keys? You've just created another kind of symbol, with unique identity, but registered and well-known symbols are still forgeable, and still share a typeof.

@hax
Copy link
Member Author

hax commented Jan 24, 2022

how does this solve one of the objection

@mhofman This alternative actually do not introduce symbol as weakmap key, so there will be no observable difference. 😂

But as @acutmore said, it can't solve "swappable objects" case. I'm not sure whether "swappable objects" are the hard requirement, if that, it seems we must introduce symbol as weakmap key.

@hax
Copy link
Member Author

hax commented Jan 24, 2022

There is no consensus on that security isolation being a viable constraint.

@ljharb

But such security isolation constraints are the consequence of the design of shadow realms, aren't they? And shadow realm is already stage 3 so doesn't it already have consensus ?

@ljharb
Copy link
Member

ljharb commented Jan 24, 2022

@hax it's part of shadow realms, but it's still not a constraint on the language to maintain 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

4 participants