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

Open Question: what to do about accessors? #4

Closed
Tracked by #1
ljharb opened this issue Sep 1, 2021 · 11 comments · Fixed by #16
Closed
Tracked by #1

Open Question: what to do about accessors? #4

ljharb opened this issue Sep 1, 2021 · 11 comments · Fixed by #16
Labels
question Further information is requested

Comments

@ljharb
Copy link
Member

ljharb commented Sep 1, 2021

When an intrinsic is an accessor property, the only use cases I have, and am aware of, require the get accessor function directly.

Although when an intrinsic is a data property getIntrinsic will just return it, one option is that when it's an accessor property, getIntrinsic returns the getter. This is what https://npmjs.com/es-abstract does, and seems the easiest to me.

Another possibility would be returning a property descriptor, but then we'd have to do that for every intrinsic - and there's no use case i'm aware of for knowing the enumerability/configurability/writability of intrinsics, and no intrinsics currently have a setter.

@ljharb ljharb added the question Further information is requested label Sep 1, 2021
@mhofman
Copy link
Member

mhofman commented Sep 1, 2021

I believe Web IDL does have an attribute concept that allows an interface to define attributes that end up exposed as getters/setters on the corresponding ECMAScript prototype objects.

@ljharb
Copy link
Member Author

ljharb commented Sep 1, 2021

True, and I believe HTML does have some setters, despite 262 having none.

That's an argument towards returning some kind of descriptor object - whether it's a full descriptor, or maybe just value or get/set.

@mhofman
Copy link
Member

mhofman commented Sep 1, 2021

An alternative would be to prefix the property name with get or set . E.g. "Map.prototype.get size" ? I doubt the 262 spec or any host would ever define a property name that includes a space.

@ljharb
Copy link
Member Author

ljharb commented Sep 1, 2021

or get Map.prototype.size, perhaps - but then what happens with Map.prototype.size directly? Would that be "not an intrinsic"?

If so, I think that could work very nicely.

@mhofman
Copy link
Member

mhofman commented Sep 1, 2021

I think I prefer Map.prototype.get size since get size is the name of the getter function, which is observable.

Map.prototype.size would not be an intrinsic.

@ljharb
Copy link
Member Author

ljharb commented Sep 1, 2021

The name isn't relevant, though, otherwise Set.prototype.keys wouldn't be an intrinsic either.

Also, there could be a function named "get" - i think Map.prototype.get size looks like an intrinsic named "Map.prototype.get" to me.

@mhofman
Copy link
Member

mhofman commented Sep 1, 2021

I didn't express myself clearly.

If %Foo.prototype.bar% is an intrinsic accessor and not a value, only 'Foo.prototype.get bar' and/or 'Foo.prototype.set bar' would represent the intrinsic, never 'Foo.prototype.bar' on its own.

Regarding syntax, an alternative to keep with the property access model would be "Foo.prototype['get bar']", with all the string escaping nightmares that entails.

@ljharb
Copy link
Member Author

ljharb commented Sep 1, 2021

Since the function name isn’t relevant, i strongly feel like your suggested string syntax isn’t viable.

We can certainly bikeshed alternatives tho - i do very much like the suggestion to differentiate the strings for data vs accessor vs mutator properties.

@mhofman
Copy link
Member

mhofman commented Sep 2, 2021

Since we're bikeshedding this, another alternative that also kinda solves the symbol issue is to take an array of path elements, which are either strings or symbols. E.g. ['Foo', 'prototype', 'get bar'] or ['Foo', 'prototype', Symbol.iterator].

However, it makes it less clear that getIntrinsic(['Foo', 'prototype', 'baz']) and getIntrinsic(['Foo', 'prototype']).baz are not equivalent.

@ljharb
Copy link
Member Author

ljharb commented Sep 28, 2021

I'd prefer to avoid the path array approach; it's added boilerplate and memory usage solely for explicitness (using a list of arguments would avoid the extra array, but wouldn't address the boilerplate concerns).

So far the best options I can see are one of:

  • always return an object, which has either a value property or get/set properties (pros: consistent API, cons: boilerplate/object creation for the common case)
  • only return such an object when the intrinsic is an accessor property (pros: simpler for the common case, cons: inconsistent API, you have to "just know" whether you're asking for an accessor or a data property)
  • use a different DSL for accessors - Map.prototype.size would fail, but get Map.prototype.size or set Map.prototype.size would not (the former would return the getter, the latter undefined, regardless of the outcome of Open Question: what happens with a missing intrinsic? #6).

I like the third option because it avoids taxing the common case, and avoids the creation of a transient container for the get/set pair.

@bathos
Copy link
Contributor

bathos commented Jan 1, 2022

or get Map.prototype.size, perhaps - but then what happens with Map.prototype.size directly? Would that be "not an intrinsic"?
If so, I think that could work very nicely.

That makes perfect sense to me — I have a strong preference for option three.

There’s a descriptor option in my lib’s DSL (#d for descriptor, #g for get, #s for set), so I can speak in the past tense and say that I’ve only found it useful a small number of times and I wouldn’t include it again if I were recreating it now. At least in web platform API stuff, retrieving get/set is very common, maybe more common than data properties, so anything that keeps that smooth is 💖.

@ljharb ljharb mentioned this issue Oct 26, 2022
24 tasks
ljharb added a commit that referenced this issue Jan 17, 2023
Fixes #2. Closes #3. Closes #4. Closes #6.
@ljharb ljharb closed this as completed in b8386d7 Jan 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants