01:12
<rkirsling>
wait for real? https://github.com/tc39/test262/blob/main/test/built-ins/Error/cause_property.js#L37
01:14
<rkirsling>
why would there be a difference between explicit `undefined` and non-existence in a options bag?
01:15
<ljharb>
rkirsling: differentiates between an error with no cause and one with a cause of `undefined`?
01:16
<ljharb>
perhaps, a “undefined is not a function” error :-p
01:16
<rkirsling>
lol
01:16
<rkirsling>
but it's not null
01:16
<rkirsling>
like, is there any precedent for that anywhere in the language?
01:17
<ljharb>
for presence and undefined being different? tons. it’s the first options bag tho
01:18
<rkirsling>
that's the thing
01:18
<ljharb>
(non-intl, at least)
01:18
<ljharb>
cause, and temporal, and growable array buffer, and import assertions, might be the first options bags, whichever lands first?
01:19
<ljharb>
but the way userland treats options bags does often pívot on presence and not undefined, i think
01:19
<rkirsling>
that would be shocking to me as a user
01:20
<rkirsling>
...assuming it resulted in anything noticeable
01:20
<ljharb>
i mean, in this case if you don’t differentiate between absent and undefined, error.cause will be undefined either way, so I’m not sure why it makes a difference :-)
01:21
<rkirsling>
because an implementation has to create a property descriptor for no reason whatsoever
01:21
<ljharb>
oh, you’re not talking about “it’s absent when absent” you’re surprised it’s present when undefined?
01:22
<ljharb>
the Get is observable
01:22
<rkirsling>
yeah like that's a userland object that may have been reused
01:22
<ljharb>
it seems strange to me to do the Get and not make the property
01:22
<rkirsling>
why would setting to undefined not be equivalent to deletion
01:22
<rkirsling>
from the API's standpoint
01:22
<ljharb>
because it’s not, for many things?
01:23
<ljharb>
anything using Object.keys/entries/values, or object spread/rest, will see the key if it’s present and undefined, but won’t if it’s absent
01:24
<rkirsling>
I mean yeah cases of enumeration are supposed to be the time where it makes a difference
01:24
<ljharb>
typically you don’t mutate objects either; you make a new one that lacks the property you don’t want
01:24
<ljharb>
I’m not sure why someone would mutate but not delete
01:24
<rkirsling>
this isn't enumerating anything, it's reaching in and taking action on undefined
01:24
<rkirsling>
I mean that was the old norm
01:24
<ljharb>
i don’t think it was
01:24
<rkirsling>
it absolutely was
01:24
<ljharb>
the old norm was delete. Then it shifted to “copy”
01:25
<rkirsling>
we have a whole webkit blog post about "hey it's no longer unperformant to use delete"
01:25
<ljharb>
the period of time where deletion was thought of as bad and mutation was also not thought of as bad is either very short or nonexistent
01:25
<ljharb>
well sure. But long before that came out, mutation fell out of vogue
01:25
<ljharb>
that there’s old code that’s now faster is great, but doesn’t affect user expectations imo
01:26
<rkirsling>
okay fine but it doesn't have to be a matter of reuse
01:26
<ljharb>
iow, that optimization was years too late to actually cause users to like using `delete`
01:27
<ljharb>
(here I’m arguing against “setting to undefined as deletion” as a justification; unrelated to whether we care about presence vs undefined or not)
01:28
<rkirsling>
if you were simply filtering existing options then you're not expecting setting undefined to do anything
01:29
<rkirsling>
`{ foo: originalOptions.foo }` or something
01:29
<ljharb>
true. but I’d expect you to spread the original object, and overwrite what you wanted, rather than doing it one at a time
01:29
<ljharb>
either way tho, having an own undefined cause property, versus lacking one - when do you expect that to cause a problem for users doing this?
01:30
<rkirsling>
I don't, I just see no benefit to having a property descriptor get created
01:31
<rkirsling>
if there's not a precedent for it then it seems like taking conscious action where none was desired
01:31
<ljharb>
right, so for these users, no difference - but for users who do care, the presence or absence of a property descriptor actually communicates something useful.
01:33
<ljharb>
unfortunately since we decided not to do an internal slot and a prototype accessor, this kind of choice comes up, but i think matching own-ness between the options bag and the error instance is actually a useful property.
01:33
<rkirsling>
it shouldn't?
01:33
<rkirsling>
like, I would call it harmful if it's viewed as not extraneous but usable
01:33
<rkirsling>
it's undefined not null
01:34
<ljharb>
why is that different
01:34
<ljharb>
Both are explicit values
01:34
<ljharb>
the belief that one means “explicitly empty” and one means “never set” is decidedly not a universal one (optional chaining and nullish coalescing operate on both, because of this)
01:35
<rkirsling>
how are you seeing optional chaining and nullish coalescing as supporting your point
01:37
<rkirsling>
it is not expected for mere existence to affect anything but enumeration
01:37
<rkirsling>
a user has no other way to opt out using an object literal
01:39
<rkirsling>
anyway I am completely exhausted and I didn't come here to debate minutiae; it genuinely seems like a bug, if there's no precedent to say otherwise
01:39
<rkirsling>
people code in different ways
01:39
<rkirsling>
this is not expected behavior
01:41
<ljharb>
i hear that you don't expect it
01:41
<ljharb>
i very much do
01:42
<ljharb>
i write code all the time that checks hasOwnProperty
01:48
<rkirsling>
was this ever pointed out in committee?
01:48
<rkirsling>
like, if this is going to be the thing to set the precedent then having such a conversation seems like a stage 4 blocker
01:50
<ljharb>
hm, not sure. If we didn’t explicitly decide it tho then i don’t think it could be a binding precedent really. I’ll try and find something in the notes and repo tho
02:02
<Bakkot>
https://github.com/tc39/proposal-error-cause/pull/26#discussion_r583989100
02:02
<Bakkot>
rkirsling ljharb ^
02:03
<Bakkot>
and also https://github.com/tc39/proposal-error-cause/issues/2#issuecomment-789375512
02:07
<rkirsling>
wow
02:07
<rkirsling>
that is fascinatingly weird
02:09
<rkirsling>
but that rationale combined with the knowledge that shu also brought this up makes me somewhat less queasy
02:10
<rkirsling>
Bakkot: are you concerned with this setting a precedent for options bag options in general though, even though the motivation here has nothing to do with that?
02:10
<Bakkot>
no, not especially
02:10
<rkirsling>
okay
02:12
<Bakkot>
like temporal has a bunch of options-bag-like cases and they all just do `get`
02:12
<Bakkot>
e.g.
02:13
<Bakkot>
which is fine, because they are not in the situation that "undefined" is a sensible value for the option to take plus also having different behavior for presence and absence of the option
02:13
<Bakkot>
that's a fairly unique scenario
02:13
<Bakkot>
I do want it to serve as precedent for options bags which meet both of those criteria, because I think it's the right behavior there
02:19
<rkirsling>
hmm
02:19
<rkirsling>
can you envision another (hypothetical) example?
02:22
<Bakkot>
not off the top of my head
02:22
<Bakkot>
most places are at least a little bit typed
02:23
<Bakkot>
the only reason this one isn't is because it's intended for use with existing untyped syntax
02:23
<Bakkot>
(namely throw/catch)
02:32
<rkirsling>
fair enough
02:32
<ljharb>
Bakkot: thanks for finding that
02:34
<ljharb>
i do agree that when `undefined` isn't a reasonable real value for an option - which will be almost every other case - then it should just do a Get
15:17
<shu>
perhaps we should introduce a 3rd nullish type to mean absent
15:17
<shu>
we can even name it *empty* so it's easily confused with ~empty~ in the spec
15:18
<ljharb>
`nil`
15:19
<shu>
will there be a separate concept of "nilish" vs "nullish"?
15:19
<shu>
then we can extend the JS trinity diagram
15:21
<ljharb>
i am reminded of https://github.com/BrendanEich/nil (which brendan resurrected but didn't create)
15:22
<shu>
oh my goodness, that toString semantics
17:17
<robpalme>
could I get a blessing here plz https://github.com/tc39/notes/pull/123
17:53
<akirose>
robpalme: i have edits. should I open a PR on your fork's branch?
17:53
<akirose>
ljharb: don't merge yet! i mean, you can, but 👆
17:55
<ljharb>
nah was just stamping per request
17:55
<ljharb>
i'll let yall handle it
19:39
<robpalme>
I won't merge. Please use suggestions on the PR.