| 00:06 | <SamB> | why does everyone know zooko, anyway |
| 04:43 | SamB | does tend to agree that trying to apply monads in a system without anything at all resembling HM-typing results in a great deal of incomprehension ... |
| 05:23 | <SamB> | now, nested promises, those I can understand readily |
| 05:34 | <hayato> | smaug____: Good point. I guess no one. AFAIK, there hasn't been much attention on that from developers. We should go though all usage of 'in a Document'. |
| 05:36 | <hayato> | smaug____: does get-current-doc mean owerDocument property? |
| 05:36 | <SamB> | krit: HTMLElement isn't renamed to Element yet? |
| 09:42 | <tobie_> | JakeA: sorry for the confusion between the FetchStore and FetchStores APIs. |
| 09:42 | <JakeA> | tobie_: No worries, sorry for the terse reply. It was 2am & I'd been woken by a thunderstorm |
| 09:42 | <tobie_> | np: I'm getting a hang of what bothers me with the current API. |
| 09:43 | <tobie_> | And have a suggestion to make. |
| 09:43 | <Ms2ger> | mathiasbynens, the js tests in wpt live there because test262 never used to accept contributions |
| 09:43 | <jgraham> | JakeA: You too, huh |
| 09:44 | <tobie_> | Ms2ger: I think that's finally getting fixed now. |
| 09:44 | <JakeA> | jgraham: yeah, it was kind amazing to watch though |
| 09:44 | <JakeA> | kinda* |
| 09:44 | <tobie_> | JakeA: here's the APIs of FS and FSs side by side, for comparison: https://gist.github.com/tobie/ecc0768343f15870ae37 |
| 09:45 | <tobie_> | FSs only operates on stores except for match. |
| 09:45 | <Ms2ger> | I still think we should merge test262 into wpt, but I'm not going to spend time arguing with tc39 |
| 09:45 | <tobie_> | Ms2ger: I agree with both of these comments. |
| 09:45 | <JakeA> | tobie_: Yeah, it's a convenience method, but really handy in practice |
| 09:45 | <tobie_> | JakeA: Have you considered moving it to the service worker instead? |
| 09:45 | <Ms2ger> | If only I was at Google, then I had someone to litigate for me at standard bodies :) |
| 09:46 | <JakeA> | tobie_: It's useful for anything that uses FetchStores |
| 09:47 | <tobie_> | JakeA: that's a good point. |
| 09:47 | <tobie_> | JakeA: are there plans to extend FetchStores beyond service workers, though? |
| 09:47 | <JakeA> | tobie_: Eg, if you're wanting to update some page content from the cache then go to the network for fresh content (or race the two), being able to do fetchStores.match('/api.json').then(r => r.body.response).then(updatePage) is useful |
| 09:47 | <jgraham> | Ms2ger: What about Attorney Anne? ;) |
| 09:48 | <JakeA> | tobie_: I want it on the window object from the start |
| 09:48 | <Ms2ger> | Is Attorney Anne back from vacation yet? |
| 09:48 | <jgraham> | No. It is still July |
| 09:48 | <Ms2ger> | SamB, HTMLElement != Element |
| 09:49 | <JakeA> | tobie_: TabAtkins: Having a debate et un on the reject vs resolve(undefined) thing https://github.com/slightlyoff/ServiceWorker/issues/374 |
| 09:49 | <tobie_> | JakeA: mmm. Shouldn't you just do fetch('/api.json').then(r => r.body.response).then(updatePage) in that case and let the SW handle the caching? |
| 09:50 | <JakeA> | Should be fetchStores.match('/api.json').then(r => r.body.asJSON()).then(updatePage) - sorry am le tired |
| 09:51 | <JakeA> | tobie_: Nah, you want the page to make two requests. One to the network via the serviceworker & one just from the cache |
| 09:51 | <JakeA> | tobie_: You could do both via the serviceworker, using headers or a querystring to make sure the sw gets the content from the correct place |
| 09:51 | <JakeA> | tobie_: But it's simpler for the page just to access the cache |
| 09:52 | <JakeA> | tobie_: the in-page code would look like https://gist.github.com/jakearchibald/766e0bffb87c87baeba3 |
| 09:57 | <tobie_> | JakeA: The use case is display cached content immediately if available, update when fresh content comes in, right? |
| 09:58 | <JakeA> | tobie_: yep, which is the super A+ offline-first way to do things (Twitter native app does the same) |
| 09:59 | <tobie_> | JakeA: thankfully, Twitter knows better and just indicates fresh content is available. |
| 10:00 | <tobie_> | JakeA: the auto-replace with fresh content found elsewhere is terrible UX. |
| 10:00 | <JakeA> | tobie_: Well, it adds the new content but updates the scroll position so you're looking at the old content still, which is great |
| 10:00 | <JakeA> | tobie_: yeah, there's a few places you can get away with it, but generally it's bad. The G+ app used to do it. |
| 10:01 | <JakeA> | Actually, I think Facebook does that |
| 10:01 | <JakeA> | still |
| 10:01 | <tobie_> | JakeA: no comments. |
| 10:01 | <tobie_> | :D |
| 10:01 | <JakeA> | :D |
| 10:02 | <tobie_> | JakeA: OK, I think you're making a convincing argument that FetchStores belongs in window. |
| 10:02 | <tobie_> | (in window too). |
| 10:04 | <JakeA> | tobie_: It's unique to the origin too, like localStorage etc. If it stays in the sw people think it's unique to the sw |
| 10:05 | <tobie_> | that doesn't bother me that much. |
| 10:08 | <tobie_> | JakeA: OK, so my proposal to move .match() on the SW itself doesn't work. :/ |
| 10:09 | <JakeA> | tobie_: What's the problem with .match on the FetchStores? It's just "give me a match from any store". Would matchAny help? |
| 10:14 | <tobie_> | JakeA: so the benefits of using just .match is that it Just Works whether you're using FSs or FS. |
| 10:15 | <tobie_> | (also its short, which people tend to prefer). |
| 10:16 | <tobie_> | The downsides, however, is it blurs the lines between FSs and FS. |
| 10:17 | <tobie_> | So as a consumer of those APIs I'm left wondering why FSs doesn't have matchAll. |
| 10:18 | <tobie_> | JakeA: Similar issue as to having FSs.get without having a FSs.set BTW. |
| 10:19 | <JakeA> | tobie_: It could have a matchAll |
| 10:19 | <JakeA> | tobie_: If you allow .set you can have the same store existing in fetchStores under multiple names, which is messy |
| 10:20 | <tobie_> | you could have that throw, no? |
| 10:22 | <JakeA> | tobie_: Yep, or just make it not-possible as in the current design |
| 10:22 | <tobie_> | So yeah, I think renaming FSs.match to FSs.matchRequest / FSs.matchAny / something that clearly marks it as a convenience method that operates directly on the requests rather than on the stores would make the whole API a lot clearer if a tad more verbose. |
| 10:23 | <JakeA> | tobie_: the create/get pattern is used in databases |
| 10:23 | <tobie_> | it's more commonly create/find |
| 10:23 | <tobie_> | no? |
| 10:24 | <JakeA> | tobie_: in IDB it's create/get, in mysql it's create/use |
| 10:25 | <tobie_> | oh boy, if we use IDB as an example we're doomed. |
| 10:26 | <JakeA> | I know, but just because idb is bad doesn't mean every pattern they exhibit is wrong |
| 10:26 | <tobie_> | I know. :) |
| 10:26 | <tobie_> | I'm used to seing get/set get/post/put/delete create/find create/select but create/get, not so much, tbh |
| 10:27 | <Ms2ger> | Everything's bad, so just throw consistency out of the window |
| 10:27 | <tobie_> | Ms2ger: honest question, what's better, consistency with a crap API or inconsistency with a Possibly better one? |
| 10:27 | <JakeA> | Anne suggested var store = new FetchStore("name"); fetchStores.add(store); |
| 10:28 | <JakeA> | fetchStores.get("name") |
| 10:28 | <JakeA> | Where fetchStores.add would throw if it already contains a store with a given name |
| 10:28 | <JakeA> | That would make Domenic happier I think. |
| 10:29 | <tobie_> | Sounds like it from his comments on the issue. |
| 10:31 | <JakeA> | I prefer fetchStores.create('name').then(store => store.add(urls)) |
| 10:31 | <JakeA> | vs var store('name'); Promise.all([store.add(urls), fetchStores.add(store)]); |
| 10:31 | <JakeA> | ffs |
| 10:31 | <JakeA> | var store = new FetchStore('name'); Promise.all([store.add(urls), fetchStores.add(store)]); |
| 10:37 | <tobie_> | Yup. I can see that causing lots of issues down the line. |
| 10:38 | <tobie_> | A whole bunch of examples I saw actually forget to wait for the store to be saved to disk before moving on to the next thing. |
| 10:44 | <tobie_> | JakeA: I guess this doesn work because fetchStores.add takes multiple stores, right? fetchStores.add(new FetchStore("foo")).then(store => store.add(urls)) |
| 10:46 | <JakeA> | tobie_: If .add resolves with the added store, that works |
| 10:47 | <tobie_> | Well, unless .add accepts multiple arguments, in which case... :( fetchStores.add(new FetchStore("foo")).then(stores => stores[0].add(urls)) |
| 10:48 | <JakeA> | tobie_: Yeah, I don't like the "multiple args resolve to array" pattern. I'd rather be like Promise.all and take an array & resolve to an array |
| 10:48 | <JakeA> | tobie_: Which is why I changed store.add to take an array |
| 10:48 | <tobie_> | Man, I wish JS had a way to abstract collections and single items somehow |
| 10:50 | <tobie_> | JakeA: both patterns are terrible, tbh. |
| 10:51 | <tobie_> | like arr.push.apply(arr, [1, 2, 3]); |
| 10:52 | <tobie_> | Or when it works the other way round: arr.push([1]); |
| 10:54 | <tobie_> | What happens if you do fetchStores.add(store) it throws? or internally converts to fetchStores.add([store]) |
| 11:52 | <JakeA> | tobie_: Here's the problem, it'll be fetchStores.add(store), but fetchStore.add([url, request, anotherRequest]) |
| 11:52 | <JakeA> | tobie_: Another good reason to stay with .create IMO |
| 11:52 | <tobie_> | oh, boy. |
| 13:13 | <Domenic> | .create as sugar for construct + add is I think my preference |
| 13:14 | <Domenic> | JakeA: tobie_: ^ |
| 13:15 | <JakeA> | Domenic: that could work |
| 13:15 | <Domenic> | (Still reading scrollback) |
| 13:16 | <tobie_> | JakeA brought up the fetchStores.add(item) but store.add(iterable) issue |
| 13:17 | <Domenic> | Ah yeah, seems annoying |
| 13:18 | <Domenic> | Also on reject vs. undefined, my only strong opinion was on a method names get. One named match I haven't thought too hard bit for now could go either way |
| 13:18 | <Domenic> | augh iPad typing ftl |
| 13:19 | <Domenic> | I would expect from Set that add takes a single argument |
| 13:19 | <Domenic> | but that might be false consistency |
| 13:19 | <JakeA> | Domenic: yeah, I spent the train journey in mocking up code using reject vs undefined. I'm favouring reject. |
| 13:19 | <Domenic> | in which case a name like put might be better? I dunno this is clearly a tough call. |
| 13:20 | <Domenic> | when I get in to work I promise to reply to all issues after actually thinking about them hard |
| 13:20 | <tobie_> | yeah, or push? |
| 13:20 | <Domenic> | push would take varargs, not iterable |
| 13:20 | <JakeA> | Domenic: store.add([url, request, otherRequest]) is an atomic operation, depending on fetching all those resources. It feels like that should reject on failure too. |
| 13:21 | <tobie_> | right that was for fetchStores. |
| 13:21 | <JakeA> | Domenic: But if you want to resolve with an array, that gets ugly |
| 13:21 | <Domenic> | JakeA: that definitely seems reasonable |
| 13:21 | <Domenic> | modulo naming |
| 13:21 | <Domenic> | resolving with an array is fine in ES6 |
| 13:22 | <Domenic> | .then(([a, b, c]) => …) |
| 13:22 | <JakeA> | Think I still prefer "cache" based names for all this :( |
| 13:22 | <Domenic> | FFs I hope iOS 8 custom keyboards let you add a bunch of programmer punctuation to the main screen |
| 13:23 | <tobie_> | add does so much stuff, no wonder it's hard to name. |
| 13:23 | <tobie_> | store.add that is. |
| 13:23 | <Domenic> | I much prefer that style of atomicity to something complicated like IDB's transactions though |
| 13:24 | <JakeA> | tobie_: Although cache.add(["/whatever.json", "/style.css"]) feels intuitive to me, but maybe I'm in too deep |
| 13:24 | <tobie_> | well, it's really fetchAndStore |
| 13:25 | <JakeA> | true |
| 13:25 | <tobie_> | store.fetch? store.prefetch? |
| 13:26 | <tobie_> | note I would love to see if people would get more upset over fetchAndStore than brand-color |
| 13:26 | <JakeA> | "add '/style.css' to this cache" makes sense to me |
| 13:27 | <tobie_> | It took me quite a while to figure out what exactly store.add was doing by just looking at the code. |
| 13:27 | <tobie_> | Feels a bit like appcache magic to me. |
| 13:28 | <tobie_> | if you see what I mean. |
| 13:28 | <Domenic> | Is it sugar for two composable reactions (fetch and add)? |
| 13:29 | <Domenic> | If so the complexity seems ok |
| 13:29 | <Domenic> | S/reactions/operations |
| 13:29 | <tobie_> | yeah, throw in a Promise.all and it is. |
| 13:30 | <JakeA> | The bit we don't have a lower-level for is the atomic put |
| 13:31 | <JakeA> | store.put(request, response) - allowing you to add custom responses & requests |
| 13:31 | <JakeA> | Could guarantee that calls to .put within the same task are atomic, but that's getting close to idb-land |
| 13:31 | <Domenic> | Noooooo bad bad |
| 13:32 | <JakeA> | agreed |
| 13:32 | <Domenic> | addRequest, with add as sugar that takes more than one URL, request, whatever? |
| 13:33 | <tobie_> | Got to run. Will catch up on the conversation later. |
| 13:34 | <JakeA> | Domenic: it's not just sugar if nothing else handles the atomic commit |
| 13:34 | <Domenic> | addRequests then? |
| 13:39 | <JakeA> | I think we need a version of .put that takes many request & response combos. But ugh. |
| 13:40 | <JakeA> | Then we could explain .add on top of that using fetch & Promise.all |
| 13:40 | <JakeA> | Actually no |
| 13:41 | <JakeA> | because we don't have a way to do a series of deletes + puts atomically, but .add does |
| 13:41 | <JakeA> | Will let it bounce round my read over the weekend |
| 14:37 | <Domenic> | maybe something more truly low-level, e.g. .atomic({ add: [...], delete: [...] }) |
| 14:39 | <TabAtkins> | +1 on making the name somehow more descriptive of the "all or nothing" semantics. I didn't get that out of .add() at all. |
| 18:56 | <Ms2ger> | gsnedders, https://i.imgur.com/6k0l9zo.jpg |
| 19:01 | <gsnedders> | Ms2ger: hah |
| 19:02 | <wilhelm> | Internet Explorer keeps Scotland safe? |
| 20:20 | <Hixie> | how big should i be making the multipage spec slices? |
| 20:20 | <Hixie> | is a megabyte ok? |
| 20:22 | <SamB> | Hixie: well, about how big do they run now? |
| 20:25 | <Hixie> | the old splitter ranged them from 15k to 650k. |
| 20:26 | <Hixie> | but imho had too many |
| 20:26 | <Hixie> | the new splitter splits them into sections from 30k to 900k, plus one outlier at 3MB. |
| 20:27 | <gsnedders> | how large is it if you just do one per top-level section? |
| 20:29 | <Domenic> | Does this mean all multipage links are going to break? :( |
| 20:29 | <gsnedders> | they all have magic that redirects based on the fragment anyway |
| 20:29 | <gsnedders> | because it's never been stable |
| 20:30 | <Domenic> | oh did not know. that's good then. |
| 20:30 | <gsnedders> | this is why you can do something really naive like http://whatwg.org/C#parsing without caring what section it lies in |
| 20:31 | <Domenic> | It would be cool to use replaceState to show a semi-canonical multipage permalink URL in the URL bar at all times |
| 20:31 | <Domenic> | like /C#fragment seems pretty good to me |
| 20:31 | <Domenic> | Change it as you scroll |
| 20:33 | <Hixie> | gsnedders: the new splitter is doing one per top-level section right now |
| 20:34 | <Hixie> | Domenic: file a bug, put "tools" in teh status whiteboard :-) |
| 20:34 | <gsnedders> | Hixie: seems more reasonable to me |
| 20:34 | <Hixie> | gsnedders: yeah, except for the 3MB one |
| 20:34 | <Hixie> | which is all the elements |
| 20:35 | <Hixie> | i guess i'll split that one up further |
| 20:35 | <Hixie> | Domenic: the multipage stuff is going to be a lot more stable because i'm hard-coding where the splits occur, and the filenames to use, in the source file itself |
| 20:36 | <Domenic> | Hixie: well, that does help. |
| 20:48 | <smaug____> | when one does var w = someotherwindow.WebSocket(); what is the entry settings object? |
| 20:53 | <Hixie> | The entry settings object is the most-recently added script settings object in the stack of script settings objects that is labeled as a candidate entry settings object. |
| 20:54 | <Hixie> | i.e. doesn't matter which Window the constructor is invoked on |
| 20:55 | <smaug____> | Hixie: right, so it is from the context of w |
| 20:57 | <Hixie> | not necessarily |
| 20:57 | <Hixie> | if w is in a function in yetanotherwindow |
| 20:58 | <Hixie> | but the script execution started in window0 |
| 20:58 | <Hixie> | it would be window0, if i'm not mistaken |
| 20:58 | <Hixie> | otherwise it would be the incumbent settings object |
| 20:58 | <Hixie> | not the entry settings object |
| 21:25 | <tobie_> | Domenic, JakeA: think we should really have a straightforward way to prime the FS in case of cache miss, e.g.: https://gist.github.com/tobie/83674a1b83e1d4d3da21 |
| 21:27 | <tobie_> | Basically `add` that fetches caches and returns the response object but for a unique resource (so you don't have to deal with getting an array back). |
| 21:38 | <tobie_> | Opened https://github.com/slightlyoff/ServiceWorker/issues/376 with the above. |
| 23:39 | <Hixie> | i'm about to replace the multipage copy of the spec with my version |
| 23:39 | <Hixie> | so let me know if anything breaks |
| 23:41 | <Hixie> | (i haven't yet done the cross-page dfn refs) |