02:34 | <devsnek> | I wonder if there's any point to implementing atomics and sab in engine262 |
02:34 | <devsnek> | could maybe validate some of the logic |
02:38 | <Bakkot> | you aren't currently using generators in engine262, right? |
02:41 | <Bakkot> | if so, it is probably not that much work to add multithreading; you just add a babel transform which turns every AO into a generator, wraps every call to an AO so that it invokes and consumes the whole generator and gives you the return value, and wraps every expression with `yield` |
02:52 | <devsnek> | Bakkot: I use generators to implement generators |
02:53 | <devsnek> | it doesn't bubble through AOs though |
02:53 | <devsnek> | kind of a mess |
02:56 | <Bakkot> | hmm |
02:56 | <Bakkot> | step one implement generators from scratch |
02:56 | <devsnek> | lol |
02:56 | <Bakkot> | step two implement multithreading by making everything a generator |
02:57 | <devsnek> | well I was thinking, I might not be able to test actual multithreading but I could at least test that the spec steps generally make sense |
02:58 | <devsnek> | I am also working on a bytecode evaluator (called "boost"), I could do more in depth validation with that if I ever finish it |
02:58 | <Bakkot> | designing a bytecode for JS is a fun exercise |
02:59 | <Bakkot> | mostly the try/finally bits |
02:59 | <devsnek> | took me a good while to realize new expressions can be two opcodes |
03:00 | <devsnek> | I do try/catch by pushing an instruction pointer and current stack depth into an array |
03:01 | <devsnek> | instruction pointer of the catch block anyway |
03:01 | <devsnek> | doesn't support finally blocks yet |
03:01 | <Bakkot> | catch is pretty easy, finally is somewhat trickier |
03:01 | <Bakkot> | getting finally right was like 25% of the entire effort of building the VM when I tried this |
03:01 | <devsnek> | I guess it's a desugaring problem |
03:01 | <Bakkot> | yup |
03:01 | <devsnek> | try finally = catch that throws at the end |
03:02 | <devsnek> | try catch finally = try catch that catches and then catch that throws |
03:02 | <devsnek> | maybe |
03:02 | <Bakkot> | `try { } catch (e) {} finally {}` is 100% equivalent to `try { try {} catch (e) {} } finally {}` |
03:03 | <devsnek> | that's fun |
03:03 | <devsnek> | actually wait it has to deal with return instructions too |
03:03 | <Bakkot> | yeah return and break are the part that make this hard |
03:03 | <devsnek> | I guess you have to push a fake return location |
03:04 | <Bakkot> | let me see if I can get permission to open source the fuzzer I wrote for this |
03:04 | <devsnek> | ooo |
03:04 | <Bakkot> | (it's the obvious thing you'd do if you set out to write a fuzzer for this problem, nothing special) |
03:04 | <Bakkot> | (just I have already written it) |
03:05 | <devsnek> | I tell myself I'll start fuzzing after I pass all of test262 |
03:05 | <devsnek> | haven't gotten that far yet |
03:05 | <Bakkot> | the fun cases are stuff like `x: try { return 0; } finally { if (Math.random() < 5) break x; }` |
03:05 | <Bakkot> | `< .5`, not 5 |
03:06 | <devsnek> | I haven't done labels yet either |
03:06 | <devsnek> | I guess that won't be too hard to add |
17:17 | <devsnek> | rkirsling: still failing like 10k tests but looking pretty good in terms of test262 coverage https://gc.gy/62624842.png |
17:17 | <devsnek> | er |
17:17 | <devsnek> | rwaldron: ^ |
20:06 | <devsnek> | I feel like this might've been brought up before but it's weird that return is sometimes an await and sometimes not |
20:06 | <devsnek> | in async vs async generator |
20:07 | <ljharb> | hm, i would assume it never needs the await |
20:08 | <devsnek> | it's better for it to include the await |
20:08 | <devsnek> | cuz of try/catch |
20:10 | <ljharb> | in the spec? |
20:11 | <devsnek> | I mean so you don't need to write `return await` |
20:13 | <ljharb> | right but you might not want the await |
20:14 | <ljharb> | the way it works in async function imo is the right way; i think there was discussion about this for async generators late in the process, but i don't remember the outcome |
20:33 | <Bakkot> | I know we discussed it for `yield`, see https://github.com/tc39/proposal-async-iteration/issues/93 |
20:34 | <Bakkot> | I would guess that `return` implicitly unwraps in async generators so that it matches `yield` |
20:34 | <Bakkot> | it is a bit odd though |
20:36 | <Bakkot> | oh, wait, that happens because the value from `return` isn't going to get wrapped in a promise |
20:38 | <Bakkot> | if `return` didn't implicit await you could end up with `{ done: true, value: [a promise] }`, which would be weird |
20:38 | <Bakkot> | (at least, I assume this is the reason) |
20:39 | <ljharb> | ah right, yes, that was the reason |
20:39 | <devsnek> | that doesn't have to be an await |
20:39 | <ljharb> | iirc, i'd have preferred syntactically requiring `return await`, but instead we went with implicit await |
20:39 | <devsnek> | it could be a `.then(fulfill)` |
20:39 | <devsnek> | pushing the error to the caller instead of the returner |
20:40 | <Bakkot> | that would be weirder still |
20:40 | <devsnek> | it makes more sense to me than the await |
20:42 | <Bakkot> | actually wait maybe I don't understand the proposal |
20:42 | <Bakkot> | what would `(async function*(){ return Promise.reject(0); })` return? |
20:42 | <Bakkot> | (and the first couple of `.next`s) |
20:43 | <devsnek> | idk off the top of my head |
20:43 | <devsnek> | i could plug my idea into engine262 in a bit |
23:56 | <Bakkot> | bradleymeck: did you have a repo for the arbitrary-module-specifiers proposal? |
23:56 | <Bakkot> | could find it on tc39/proposals |