| 03:19 | <ljharb> | is it weird to anyone else that https://tc39.es/ecma262/#sec-property-descriptor-specification-type says that an empty Record is a Property Descriptor? |
| 03:33 | <bakkot> | it is, though |
| 03:33 | <bakkot> | that's so Object.defineProperty(foo, 'bar', {}) works |
| 07:32 | <ljharb> | i mean i get that an empty object has to work in a number of places. but since { enumerable: true } isn't a property descriptor record either (that'd be { [[Enumerable]]: true }) i'm not sure why an empty record needs to be one |
| 17:24 | <bakkot> | if you look at how Object.defineProperty works it basically mechanically converts the object into a spec record by copying over each of the relevant fields https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-topropertydescriptor |
| 17:26 | <bakkot> | and then passing it to definePropertyOrThrow which switches on presence of various fields |
| 17:32 | <bakkot> | it could work some other way but the reason an empty record is a property descriptor record is to allow it to be written this way |
| 17:34 | <bakkot> | I think if we were writing it today we'd probably avoid having optional fields in the record, which we usually avoid, but it would require a bit more machinery |
| 17:45 | <ljharb> | I definitely understand why it's written this way |
| 17:46 | <ljharb> | i'm wondering if it would be cleaner to special-case "no fields" rather than having the bottom type of all records be Property Descriptor |
| 18:01 | <bakkot> | ah |
| 18:01 | <bakkot> | I prefer not to; I don't think of records as really sharing types |
| 18:02 | <bakkot> | it's not like you come across a random record with no context in the spec; they're always being passed around between specific algorithms which make it clear what kind of thing they're working with |
| 18:25 | <Michael Ficarra> | lmao is this guy trying to save disk space on GitHub's servers? https://github.com/tc39/ecma262/pull/3478#issuecomment-2589138113 |
| 18:25 | <Michael Ficarra> | who does this? |
| 18:29 | <jmdyck> | Maybe he's saving space locally then pushing to github? |
| 18:45 | <jmdyck> | ljharb: Given Let _e_ be Record {}. If _e_ is a Property Descriptor, then ..., are you thinking that the condition would succeed? |
| 18:47 | <ljharb> | who does this? |
| 18:47 | <ljharb> | ljharb: Given |
| 18:49 | <jmdyck> | So you think "is a Foo Record" could be true of any record, regardless of how created, as long as it only has fields that a Foo Record can have? |
| 18:51 | <ljharb> | yes, we have structural not nominal typing on records |
| 18:53 | <jmdyck> | What suggests this to you? |
| 18:56 | <bakkot> | well, we do for property descriptors specifically per the introductory paragraph of https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-property-descriptor-specification-type |
| 18:57 | <bakkot> | I think/hope that everywhere else in the spec the difference would be never be observable; we're not really switching on the types of internal records much (ever?) |
| 18:58 | <shu> | there're a few places around Reference Records, and class fields |
| 18:59 | <shu> | but yes i also hope the difference is never observable |
| 19:00 | <shu> | more specifically i hope, for named records, we never create record literals without the name (but with all the fields) and use it like the named records |
| 19:02 | <bakkot> | ooh, found one but it's silly https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-symbol.for |
| 19:02 | <jmdyck> | bakkot: you're saying that that intro paragraph says that property descriptors have structural not nominal typing? |
| 19:03 | <shu> | oh boo but at least it's right above the table |
| 19:03 | <bakkot> | jmdyck that's my reading of it yes:
|
| 19:04 | <bakkot> | I also really dislike the reference to the ambient "GlobalSymbolRegistry List" in Symbol.for |
| 19:05 | <bakkot> | I'm sure Michael Ficarra dislikes it more |
| 19:05 | <jmdyck> | oh, the second paragraph, hm. |
| 19:05 | <bakkot> | oh sorry yes |
| 19:06 | <shu> | but it really is so global |
| 19:06 | <shu> | it transcends all realms |
| 19:06 | <bakkot> | yes but we should <dfn> it or something at the very least |
| 19:07 | <shu> | yeah, and... i guess we should also build in locking? |
| 19:07 | <bakkot> | oh yeah fun |
| 19:07 | <bakkot> | we can just handwave that |
| 19:07 | <bakkot> | actually, would it be observable? they're not structured-cloneable |
| 19:09 | <jmdyck> | (GlobalSymbolRegistry is called out in MF's 2724: https://github.com/tc39/ecma262/issues/2724#issuecomment-1093579455) |
| 19:09 | <bakkot> | ah, good good |
| 19:10 | <shu> | i didn't realize they weren't actually |
| 19:10 | <bakkot> | symbols aren't cloneable at all |
| 19:10 | <bakkot> | it's a bit silly |
| 19:10 | <bakkot> | registered symbols probably should be |
| 19:11 | <bakkot> | https://html.spec.whatwg.org/multipage/structured-data.html#structuredserializeinternal step 5 |
| 19:12 | <shu> | that is eminently silly yes |
| 19:19 | <jmdyck> | I think you can read the second para of 6.2.6 as classifying values that you've already established are Property Descriptors. So it doesn't address whether an empty schema-less Record qualifies as a Property Descriptor. |
| 19:22 | <bakkot> | right, yeah; by "we have structural typing for property descriptors" I meant only "within the property descriptor type we have structural typing", not that we have it for discriminating property descriptors from other kinds of things |
| 19:32 | <jmdyck> | okay, so to the question of Given Let _e_ be Record {}. If _e_ is a Property Descriptor, then ..., does the condition succeed, your answer is (roughly): the spec doesn't say, and I hope there's never a case where we'd need an answer ? |
| 19:33 | <jmdyck> | (such a case would be an editorial error?) |
| 19:34 | <bakkot> | correct |
| 19:35 | <bakkot> | though the one case in Symbol.for needs fixing for that to be strictly true |
| 19:35 | <jmdyck> | i don't understand the Symbol.for example. |
| 19:36 | <jmdyck> | what exactly? |
| 19:36 | <bakkot> | we create a record with specific fields, and do not call out that it is a GlobalSymbolRegistry Record, and then put it in a list of GlobalSymbolRegistry Records |
| 19:36 | <shu> | jmdyck, specifically step 5 |
| 19:36 | <bakkot> | this implies that an anonymous Record having the fields of a GlobalSymbolRegistry Record is sufficient to be a GlobalSymbolRegistry Record, i.e., it implies we are using structural typing for records |
| 19:44 | <jmdyck> | gotcha. |
| 19:45 | <jmdyck> | In my static analysis, that's the only error of that kind. |
| 19:47 | <jmdyck> | It goes back to ES6. |
| 19:51 | <jmdyck> | Re GlobalSymbolRegistry transcending all realms, see https://github.com/tc39/ecma262/issues/824 |
| 19:54 | <shu> | wait, does each agent have its own registry? |
| 19:54 | <shu> | i thought it was truly global to the agent cluster, but i may be misremembering since i also thought this was observable (but turns out it isn't due to structured cloning not working) |
| 19:54 | <bakkot> | all we know is "The GlobalSymbolRegistry is an append-only List that is globally available. It is shared by all realms." |
| 19:55 | <bakkot> | I would parse "globally available" as meaning "across agent" but it's not observable so /shrug |
| 20:12 | <jmdyck> | AWB thought that GlobalSymbolRegistry was per-Agent: https://github.com/tc39/ecma262/issues/882#issuecomment-293334655, which was quoted in issue 1357. |
| 21:11 | <ljharb> | even without that section, if i make a record and give it all the slots of an X record, how is it not thus an X record? |
| 21:12 | <Michael Ficarra> | @ljharb we just try not to do that |
| 21:12 | <Michael Ficarra> | if something needs a record of a particular kind, I construct it with that in mind |
| 21:22 | <jmdyck> | ljharb: you have a mental model in which it is, I have a mental model in which it is not. The spec appears to be non-committal / allow both. |
| 21:22 | <ljharb> | i totally get we'd try not to do that |
| 21:23 | <ljharb> | but if the spec allows for structural, then it can't possibly be nominal, mental models notwithstanding |
| 21:24 | <ljharb> | (i'm fine with making one or the other explicit, to be clear) |
| 21:25 | <jmdyck> | how do you figure "can't possibly be"? |
| 21:25 | <ljharb> | because if it's allowed to not be nominal, then it's not nominal? |
| 21:26 | <ljharb> | iow there's nothing in the spec preventing me passing a normal empty record where a Property Descriptor is allowed, ∴ it's allowed |
| 21:26 | <jmdyck> | the editors might prevent that. |
| 21:27 | <jmdyck> | deeming it an editorial error. |
| 21:31 | <bakkot> | anything pattern the spec doesn't do or give meaning to is something with no meaning |
| 21:32 | <bakkot> | it's a document |
| 21:32 | <bakkot> | you can write whatever words you want but you can't rely on readers knowing what those words mean unless they're unambiguous or spelled out |
| 21:33 | <bakkot> | you can't just say "I knew it was structural when I was writing it so it's fine" and assume the reader will also know that |
| 21:34 | <jmdyck> | Whether the spec lets you pass a schemaless empty Record where a Property Descriptor is allowed is basically the same question as whether the condition succeeds in Let _e_ be Record {}. If _e_ is a Property Descriptor, then .... And bakkot says the spec does not answer that question, and shouldn't need to. |
| 21:34 | <bakkot> | fortunately as long as we never introduce a place where it would matter we'll never have to clarify which it is |
| 21:40 | <jmdyck> | If you could write arbitrary pseudo-code and some procedure had to give you the result, then the question would need to have an answer. But that's not the situation. |
| 21:48 | <jmdyck> | My static-analysis code would complain if it saw such a thing. Don't know about esmeta. |
| 22:03 | <ljharb> | downstream specs could, though, so i still think it's worth clarifying |
| 23:00 | <bakkot> | downstream specs can do lots of things we'd rather they not do but we shouldn't make it easier for them |
| 23:28 | <ljharb> | i agree, i'm not asking for that :-) |
| 23:29 | <ljharb> | i'm asking to make it harder for them by making records nominal, and/or making an empty record not be a property descriptor |
| 23:50 | <bakkot> | explicitly making records nominal would let downstream specs rely on records being nominal, which we don't want them to do |
| 23:54 | <jmdyck> | hm. what would it look like to "rely on records being nominal"? What could someone write that you wouldn't like? |
| 23:59 | <ljharb> | ok, then explicitly make them structural, and still make an empty record not be anything |