| 11:29 | <MikeSmith> | botie, inform zcorpan when you have some time, I wanted to ask you about <picture> test cases |
| 11:29 | <botie> | will do |
| 14:14 | <JakeA> | If I want to return an interface like { foo, bar } where foo & bar are readonly arrays of strings, what type should I use? FrozenArray? Array? https://heycam.github.io/webidl/#idl-sequence says I shouldn't use a sequence. |
| 14:16 | <JakeA> | To make the example real: the object is a user contact, and the properties are `email` and `tel`, but a user can have many emails and tel numbers |
| 14:16 | <jenny-m> | pretty sure FrozenArray is the answer |
| 14:19 | <JakeA> | jenny-m: https://html.spec.whatwg.org/multipage/comms.html#messageevent uses `FrozenArray` for `ports`, so that confirms it I think. Ta! |
| 17:43 | <TabAtkins> | JakeA: If you're *returning* a value like that, you can use `sequence<>` (and probably should). |
| 17:43 | <TabAtkins> | You just can't use sequence for an attribute. |
| 17:44 | <JakeA> | TabAtkins: it'd be returning an object that has arrays as properties |
| 17:44 | <TabAtkins> | An object as in an interface, or a record? |
| 17:44 | <JakeA> | Hmm, I'd need to look up the difference |
| 17:45 | <TabAtkins> | Did you type it out as `interface Foo {...}`? |
| 17:45 | <TabAtkins> | (or a dictionary) |
| 17:46 | <JakeA> | I recommended interface, but that can change |
| 17:47 | <JakeA> | I don't think I'd use dictionary/record unless the keys were potentially different each time. Wdyt? |
| 17:47 | <JakeA> | Eg, `JSON.parse` would return a dictionary/record in idl land |
| 17:48 | <JakeA> | But if I was always returning a thing that had keys "email" and "tel", that feels like an interface |
| 17:56 | <TabAtkins> | Usually interface is the right thing yeah, but sometimes, if you're just returning some raw information, a plain-ol-JS-object (aka a dictionary or record) is appropriate. Are there methods on the thing? |
| 17:56 | <TabAtkins> | (Dictionaries always have the same keys too, that's not a differentiator from interfaces.() |
| 17:56 | <TabAtkins> | ) |
| 18:03 | <Mek> | and records have the same type for all their values, so probably wouldn't be what JSON.parse returns either. It probably would just return a plain `object` in IDL land... |
| 18:04 | <JakeA> | No methods on it. Hmm, can't decide. |
| 18:05 | <Mek> | I think I would just return a dictionary in that case? Presumably it's not live-updating attributes, but returning a snapshot of state when the object was created? |
| 18:06 | <JakeA> | Yeah, it's just a snapshot |
| 18:13 | <JakeA> | Yeah, I'll go with a dictionary then |
| 18:17 | <TabAtkins> | Yeah, dict is appropriate if it's just a snapshot of some state with no methods on it. (And no plans to add methods in the future.) |
| 18:17 | <JakeA> | When I create a instance of an IDL type, when is the equivalent platform object created? Is the platform object 1:1 with the IDL type instance? |
| 18:18 | <TabAtkins> | (Later upgrading a dictionary to an interface is possible, but technically has behavior differences that might be exercised. They're very minor tho.) |
| 18:18 | <TabAtkins> | Yes, 1:1. |
| 18:18 | <JakeA> | Good, phew |
| 18:18 | <TabAtkins> | Your internal algorithms should be operating on IDL or Infra values, and just assume that they *are* the platform objects. |
| 18:19 | <JakeA> | I don't think we should assume infra values are platform objects |
| 18:19 | <JakeA> | They might live entirely "in parallel" |
| 18:19 | <JakeA> | Where platform objects cannot exist, right? |
| 18:20 | <TabAtkins> | Oh wait, by "platform" do you mean the JS objects that authors use? |
| 18:20 | <TabAtkins> | Or the internal objects that the browser uses? |
| 18:20 | <JakeA> | Ah, I meant JS I objects |
| 18:21 | <JakeA> | Wrong term? |
| 18:21 | <TabAtkins> | dunno |
| 18:21 | <TabAtkins> | Anyway, the JS objects are magically created from IDL at the moment you pass the IDL value to author code, via a return value. (And vice versa via a method argument) |
| 18:21 | <TabAtkins> | (where "return value" and "argument" also cover the attribute getter/setters) |
| 18:22 | <TabAtkins> | And yeah, Infra objects never become JS, they have to be laundered into IDL first. |
| 18:22 | <JakeA> | So if I return the same IDL instance twice, I'm not guaranteed the same JS object twice? |
| 18:22 | <TabAtkins> | The algo should be clear on whether it's the same or not. |
| 18:22 | <JakeA> | How? |
| 18:22 | <TabAtkins> | Specify caching or not. |
| 18:23 | <JakeA> | What would I cache? |
| 18:23 | <TabAtkins> | IDL doesn't really have object identity, so it's not obvious from principles. |
| 18:23 | <TabAtkins> | Heh, gimme a concrete example and I can help more. |
| 18:24 | <JakeA> | Eg a `.loaded` getter that returns the same promise unless the "src" changes |
| 18:24 | <TabAtkins> | Okay, so then you create an IDL object, and cache it. |
| 18:25 | <JakeA> | But I thought there was no guarantee that returning the same IDL object would map to the same JS object? |
| 18:25 | <TabAtkins> | Plz don't read too much into my "magically created", I just meant you don't need to do anything special to make the JS object happen. |
| 18:25 | <TabAtkins> | JS<->IDL is understood to be 1:1 |
| 18:26 | <TabAtkins> | You, the spec author, just never ever touch the JS object unless you ahve a *very* good reason and a smart person holding your hand (not me). |
| 18:26 | <JakeA> | Just to confirm, if I pass the same IDL instance back twice, the two JS objects at the other end will be `===`, right? |
| 18:26 | <TabAtkins> | yes |
| 18:27 | <TabAtkins> | But you do have to be explicit that it's the same IDL instance which was cached between calls. ^_^ |
| 18:27 | <JakeA> | Gotcha! Phew, I thought for a moment there my whole understanding of specs was coming crashing down |
| 18:28 | <TabAtkins> | hehehe |
| 18:28 | <JakeA> | One last one⦠can I create instances of IDL types "in parallel"? |
| 18:29 | <JakeA> | (Assuming that the JS object creation happens later, when I return it on the main thread) |
| 18:29 | <TabAtkins> | Yes, you can *create* them. You just can't cause an author-observable update to anything while "in parallel". |
| 18:29 | <TabAtkins> | (pretty sure, but Domenic should confirm) |
| 18:30 | <TabAtkins> | (just in case there's actually some state dependency I'm not aware of) |
| 18:30 | <JakeA> | Gotcha. My (wrong) assumption that JS objects are created at the same time led me to only create IDL instances on the main thread |
| 18:31 | <JakeA> | But it wouldn't be observable, so fine |
| 18:40 | <JakeA> | I think was confused me was seeing instances of interfaces created in a given realm. |
| 18:40 | <JakeA> | That made it feel like JS object creation happened then, and it must therefore be on the JS thread. |
| 18:41 | <JakeA> | I think what confused me* |
| 18:42 | <TimothyGu> | JakeA: hmm I remember it to be the exact opposite |
| 18:42 | <TimothyGu> | IDL object is defined to be identical to the JS object |
| 18:43 | <TimothyGu> | numbers, etc. are probably fine |
| 18:44 | <JakeA> | Not sure I understand. I'm talking more about instantiation than definition |
| 18:44 | <TimothyGu> | as in "create a β¦ object"? |
| 18:45 | <JakeA> | Yeah "Let |whatever| be a new {{Whatever}}" |
| 18:47 | <TimothyGu> | I'm not 100% sure but from what I remember this shouldn't be allowed |
| 18:48 | <JakeA> | If I wanted to create an instance of {{Whatever}}, how should I do that? |
| 18:50 | <JakeA> | In order for, say, the `window.navigator` getter to return an instance of `Navigator`, and instance of the IDL interface `Navigator` must be created somewhere. |
| 18:50 | <JakeA> | an instance* |
| 18:51 | <TimothyGu> | JakeA: hmm for that generally you could do something like "Each {{Window}} object has an associated <dfn>navigator</dfn>, which is a {{Navigator}} object." |
| 18:52 | <TimothyGu> | and then at the same time as when the Window object is instantiated the Navigator object would be too |
| 18:52 | TimothyGu | reads up on the log |
| 18:52 | <JakeA> | TimothyGu: but that's just handwaving around creating an instance of Navigator, right? |
| 18:53 | <TimothyGu> | JakeA: well, not really. This construct is supposed to parallel something like `class Window { Navigator navigator; }` in C++ |
| 18:54 | <TimothyGu> | i.e., the Navigator is created at the same time as the Window, because a window _has_ a navigator |
| 18:56 | <TimothyGu> | an implementation might actually hold off on creating the Navigator object until it is first accessed, but that's considered an implementation detail |
| 18:56 | <JakeA> | TimothyGu: so step 29 and 31 of https://fetch.spec.whatwg.org/#dom-request is incorrect? |
| 18:58 | <JakeA> | Or step 8 of https://url.spec.whatwg.org/#dom-url-url to go for a smaller example |
| 18:58 | <TimothyGu> | JakeA: they are fine, but also different from the navigator example |
| 18:58 | <TimothyGu> | for example the "has an associated ... object" pattern is used for https://url.spec.whatwg.org/#concept-url-query-object |
| 18:59 | <JakeA> | TimothyGu: but 100% like my "let |whatever| be a new {{Whatever}}" example, right? |
| 18:59 | <TimothyGu> | JakeA: yeah but I thought you were asking about "in parallel"? |
| 18:59 | <TimothyGu> | the constructors don't run in parallel |
| 19:00 | <JakeA> | TimothyGu: but not all interfaces have constructors |
| 19:01 | <Mek> | (probably unrelated to this discussion, but) they generally should have constructors |
| 19:01 | <TimothyGu> | okay I feel like we are talking about something different |
| 19:01 | <TimothyGu> | "new {{β¦}}" don't run the constructor, at least in most cases |
| 19:03 | <JakeA> | I guess I'm still in the dark on whether instances of IDL types can be created while "in parallel" π |
| 19:04 | <Mek> | I don't think you can create a new instance of an IDL type in parallel, no |
| 19:04 | <Mek> | but also agree that running of constructors is more or less unrelated |
| 19:04 | <JakeA> | Gotcha. Good to know I haven't been doing that unnecessarily π |
| 19:06 | <TimothyGu> | I feel like this is sufficiently confusing to warrant some guidance in HTML |
| 19:06 | <Mek> | probably webidl rather than html, but yes |
| 19:07 | <JakeA> | Either. HTML defines "in parallel" |
| 19:07 | <TimothyGu> | Mek: "in parallel" is defined in HTML though, and IDL doesn't really know about parallelism |
| 19:07 | <Mek> | one issue is how idl objects are associated with realms, for which for now idl says " The mechanisms for associating objects with Realms are, for now, underspecified" |
| 19:07 | <TimothyGu> | Mek: that's really only an issue for non-platform objects |
| 19:07 | <JakeA> | Yeah, that's what got me thinking that the JS object is created when the IDL object is created |
| 19:08 | <TimothyGu> | for platform objects there's always a [[Realm]] slot |
| 19:08 | <TabAtkins> | I was pretty sure you could create IDL objects in parallel. I'd be somewhat surprised if that wasn't the case. |
| 19:08 | TimothyGu | files issue |
| 19:08 | <JakeA> | TimothyGu: but if you're creating an instance, how does it know what realm to put it in? |
| 19:09 | <Mek> | https://heycam.github.io/webidl/#es-platform-objects seems to be the section that we're talking about, right? |
| 19:09 | <Mek> | that defines the algorithms you should call when creating a new object for some IDL interface |
| 19:09 | <TimothyGu> | JakeA: that is https://github.com/heycam/webidl/issues/135 |
| 19:10 | <Mek> | ah yes, the third bullet point there is pretty explicit that creating them in parallel is okay, as long as you're explicit about the realm |
| 19:10 | <JakeA> | TimothyGu: but if you've gone parallel, then queued a task, does that association hold? |
| 19:11 | <TimothyGu> | JakeA: what association? |
| 19:11 | <JakeA> | Ah yes the third bullet point answers my question too |
| 19:11 | <Mek> | (but later discussion in that thread seems to also ask if we really should allow creating objects from in parallel) |
| 19:12 | <JakeA> | TimothyGu: there's no longer a "this" if you've queued a task |
| 19:13 | <JakeA> | Unless you kinda handwave it as being "the context object from which the parent steps were called" |
| 19:13 | <TimothyGu> | JakeA: I think that handwaving is fine |
| 19:13 | <TimothyGu> | bc specs already assume all "local variables" are captured anyway |
| 19:14 | <JakeA> | Fair |
| 19:14 | <Mek> | well, for queueing a task it probably makes more sense to somehow derive the realm from where the task is queued on, rather than who queued the task (i.e. postmessage posting a task to a different global) |
| 19:14 | <JakeA> | Also true |
| 19:14 | <Mek> | so https://github.com/heycam/webidl/issues/135#issuecomment-286789309 seems pretty reasonable to me... But I guess if one thing is clear from that thread it is that currently there are no well defiend semantics... |
| 19:16 | <JakeA> | Good to know my questions aren't stupid, at least |
| 19:22 | <TimothyGu> | Ah there's more. https://html.spec.whatwg.org/multipage/infrastructure.html#parallelism has an example with rejecting promises with a new TypeError object in parallel, but in https://github.com/whatwg/notifications/issues/113#issuecomment-349292187 annevk explicitly says resolving a promise in parallel isn't allowed |
| 19:26 | <TabAtkins> | Right, that's because it's observable - it enqueues promise callbacks, and their ordering wrt other timing-based callbacks is author-observable (and thus can't be done while in parallel). |
| 19:26 | <TabAtkins> | So yeah that's an error. |
| 19:39 | <TimothyGu> | Filed https://github.com/whatwg/html/issues/4669 to hopefully sort out this mess |
| 19:44 | <annevk> | Thanks TimothyGu |