00:12
<yusukesuzuki>
btw if anybody else didn't get added to the Tokyo 2024 channel, please do speak up!
Oh! Could you add me too? Thanks!
00:44
<Rob Palmer>
Has anyone dialled in yet?
00:45
<rkirsling>
Oh! Could you add me too? Thanks!
It says you've already been added!
00:46
<yusukesuzuki>
Oops! Thank you!!
00:50
<Rob Palmer>
We are prepping to start. If you wish to help, please sign up to a session for Note Editing! https://github.com/tc39/Reflector/issues/537#issuecomment-2394180693
00:54
<Rob Palmer>
The Teams call is up! Please rember to NOT sign into Teams itself. Join the call as a guest.
01:27
<littledan>
We have 4 slots for non-ordinary members in ExeCom
01:27
<littledan>
there are more slots than current members. I encourage everyone to join!
01:32
<shu>
Chris de Almeida: the wintercg vote
01:34
<Chris de Almeida>
shu: maybe DE can elaborate, but my understanding is that they are going to fully move to Ecma, rather than have the split of the CG vs WG
01:34
<Chris de Almeida>
the IPR concerns were due to doing some things in w3c and then some things in ecma and that was problematic
01:34
<shu>
last time that move was voted on and the vote failed due to IPR concerns. i am asking a clarification on what has changed since then
01:35
<shu>
because what i hear internally is "it's pending legal review", and aki's presentation makes it sound like it's a done thing
01:35
<canadahonk>
I can talk on this if people want
01:35
<canadahonk>
shu: maybe DE can elaborate, but my understanding is that they are going to fully move to Ecma, rather than have the split of the CG vs WG
but this is the tl;dr yeah
01:36
<littledan>
If you're interested in the founding documents, please let me know and I'll send them to you. I've already sent to Chris Wilson and Tantek Celik, in addition to the Ecma ExeCom.
01:36
<shu>
specifically i'm wondering are you doing the thing where you're sending all the contributors IP transfer documents or whatever
01:36
<littledan>
specifically i'm wondering are you doing the thing where you're sending all the contributors IP transfer documents or whatever
yes, and this is OK since it's a one-time thing rather than an ongoing operation
01:37
<shu>
is that thign pending legal review from the original folks who raised the IP concerns
01:38
<littledan>
is that thign pending legal review from the original folks who raised the IP concerns
I don't know who it's pending legal review from. The people who raised concerns previously who I've been able to follow up with were positive about this version. I haven't been able to follow up with everyone.
01:40
<shu>
i'm assuming at least mozilla and google legal
01:43
<bakkot>
fwiw the audio sounds fine on the call
01:45
<Aki>
Someone wanna drop that screenshot of TCQ questions for me so I can answer them here?
01:46
<Chris de Almeida>
we shouldn't paste here
01:46
<shu>
(mine was answered in the chat just now)
01:47
<canadahonk>
Someone wanna drop that screenshot of TCQ questions for me so I can answer them here?
I don't think there was anything else not already answered here (just re tc55 original proposal ipr things)
01:47
<Aki>
Chris de Almeida sent me the screenshot (thanks!)
01:48
<Ashley Claymore>
Ben: when you get a chance could you add a slides link to the agenda
01:48
<Ben>
Doing now
01:48
<littledan>
suggestion for Mozilla's concerns about being able to review the agenda: We require all agenda items to be added before the deadline, unless there is a particular "emergency"/reason for why the addition was delayed. We strongly encourage slides, repos or other supporting materials to be added to the agenda before the deadline or soon after it, with their contents done as early as possible.
01:56
<yulia>
the suggestions dan made above (slides & content must be available) makes a lot of sense. I would also suggest (to avoid issues in the future) that we move the deadline to 14 days (in line with ecma), and we have an indication of the amount of work (in hours) so far added to the meeting. We can't approve what we don't review, and we want to make sure that the output of tc39 is as high as possible. I think that is a shared goal. If we can plan our meeting a bit better I think it would help.
01:57
<yulia>
I am not sure if many delegates are reviewing all proposal before the meeting, but it is a requirement for us as implementers, because if something lands and we didn't really think about it -- we are left holding the bag
01:57
<Chris de Almeida>
Ecma rules say 21 days
01:57
<ljharb>
fwiw those suggestions are already the case. supporting materials that aren't in by the deadline allows for procedural blocking
01:57
<yulia>
ah my mistake
01:58
<littledan>
we've confirmed with Ecma in the past that TC39 may adopt its own deadline (otherwise I would've worked on getting the rules changed). But 14 days seems reasonable to me.
01:58
<shu>
at least for proposals 2.7+ i think an earlier deadline makes sense
01:58
<Aki>
yeah i was having a conversation the other day about this and surprised to discover TC39's deadline was different from Ecma's, i totally forgot
01:58
<yulia>
the current 5 working days that we have to fully review all of the proposals was not enough
01:58
<ljharb>
i'm not sure how we could calculate how much review work is needed, because it won't correlate with timebox time
01:59
<ljharb>
i'd assume the largest review is needed for 1 → 2 or 2 → 2.7, and the smallest for a stage 0 → 1 or 2.7 → 3 or 3 → 4
02:00
<shu>
i'd assume the largest review is needed for 1 → 2 or 2 → 2.7, and the smallest for a stage 0 → 1 or 2.7 → 3 or 3 → 4
the 2->2.7 is the biggest one IMO, because that's starting to approach the "impls left holding the bag in case of things missed during review"
02:00
<shu>
so at least in terms of irreversible consequences
02:00
<yulia>
yeah 2->2.7 is the biggest, that means that things that are not that, end up getting the short end of the stick
02:00
<ljharb>
so given that, requiring an earlier deadline for attempting to enter 2 or 2.7 might make sense (no need to require it for the others)
02:00
<bakkot>
fwiw I also did not notice that the agenda item contained "TG4: Source Map Specification, 2024 edition approval (30m, Jonathan Kuperman)"
02:00
<bakkot>
mostly because I do not look at the task group updates section
02:00
<Chris de Almeida>
I don't have strong feelings on this but I do not want a complex rules engine for which deadlines apply to which stages
02:01
<yulia>
same, i would say just an earlier deadline allowing more than 5 days of review time
02:01
<shu>
then we probably do want to move the deadline up earlier for all proposals
02:01
<littledan>
I don't have strong feelings on this but I do not want a complex rules engine for which deadlines apply to which stages
I agree, I'd prefer to have a single deadline to apply to all agenda items, not just advancement requests
02:01
<Chris de Almeida>
+1
02:01
<ljharb>
we have never had a deadline for non-advancements and i don't think we should start now
02:01
<yulia>
i believe we are only discussing advancement deadlines
02:02
<Chris de Almeida>
I think it would remain a 'best effort' thing, not a 'you missed the boat, sorry' thing
02:02
<ljharb>
the word "deadline" refers to the latter ime ("dead" being a somewhat final state)
02:02
<Chris de Almeida>
but it's very helpful if everything is in before the given date
02:02
<littledan>
well, I raised non-advancement-requests, but I can accept if we don't adopt the policy that I suggested
02:02
<Chris de Almeida>
and the later things get added, the more problems it creates
02:02
<yulia>
yeah, with the risk of something beling blocked -- i mean it would be the same situation as now, but with 2 weeks (10 days of working time, if there are no holidays) would go a long way here
02:03
<littledan>
adding something to the TC39 agenda is asking everyone to take time to focus together on a topic, so I think it's not too much for it to apply to everything. It will help us to be more effective if we have all supporting materials for all items ahead of a deadline.
02:03
<ljharb>
part of the reason we wanted to keep the deadline short in the past is that there's only 2 months between plenaries
02:03
<ljharb>
those extra 4 days have been very helpful in the past to get ducks in a row for an upcoming plenary
02:07
<yulia>
That said, since we meet so frequently, spilling over to the next meeting isn't a huge delay.
02:07
<rkirsling>
fwiw I also did not notice that the agenda item contained "TG4: Source Map Specification, 2024 edition approval (30m, Jonathan Kuperman)"
I am actually confused whether this is the appropriate timing for a topic of this nature
02:07
<ljharb>
2 months is a significant delay, but 4 days doesn't seem like one to me
02:07
<rkirsling>
like, 30m topic in the 5m topics section
02:07
<Ashley Claymore>

Current doc for advancement to Stage 1 says:

Such proposals must link to a proposal repository and they should link to supporting materials when possible.

02:07
<yulia>
the time taken in those 4 days, vs incomplete review and missing something, the cost of the latter is much higher
02:08
<Ashley Claymore>
maybe we should make that should a must
02:08
<littledan>
those extra 4 days have been very helpful in the past to get ducks in a row for an upcoming plenary
I think that logic made sense at the time, but as the committee grew and we got more topics on the agenda, the tradeoff shifts, as yulia says
02:08
<nicolo-ribaudo>
I'm not following the chat, but if it's for source map: it would be a 6 months delay and not 2 months, due to the GA meeting twice per year
02:08
<rkirsling>
maybe we should make that should a must
I feel like I remember having a conversation in which I suggested this and we landed on "should" instead somehow...or something
02:08
<Michael Ficarra>
maybe we should make that should a must
I think it's fine to have reduced requirements for Stage 1
02:09
<Aki>
I'm not following the chat, but if it's for source map: it would be a 6 months delay and not 2 months, due to the GA meeting twice per year
Two months here refers to stage advancement
02:10
<littledan>
overall, the wording in the agenda doc has encouraged people to not bother to especially try to get things into the agenda ahead of time, even when they maybe could've. It's been confusing for me to explain to people that they really should put everything there earlier, and I've had to clarify that lots of times.
02:10
<nicolo-ribaudo>
littledan Btw, the reason we were thinking about the license for the spec itself, is that both ECMA-262 and ECMA-402 are published under Ecma's BSD version
02:15
<littledan>
littledan Btw, the reason we were thinking about the license for the spec itself, is that both ECMA-262 and ECMA-402 are published under Ecma's BSD version
Ecma has one BSD version for test262 at https://ecma-international.org/policies/by-ipr/ecma-international-policy-on-submission-inclusion-and-licensing-of-software/ ; the alternative copyright notice at https://ecma-international.org/policies/by-ipr/ecma-text-copyright-policy/ (second section) seems broadly BSD-like, but somewhat different text, which is why I was confused. I imagine you're working on the latter relicensing (I don't really understand why it's not implicit based on Google+Mozilla's agreements with Ecma, but the lawyers will known better)
02:16
<Chengzhong Wu>
do we have a slides link to TG5 Report?
02:17
<yulia>
https://docs.google.com/presentation/d/156wJbnrIEt-hbkhh0paVAIjrG9L7oe_R9z211yS0bIA/edit#slide=id.g308ab6c6cfb_0_25
02:17
<bakkot>
yulia: would you put a brief summary of the TG5 presention in the notes? there's a spot for it
02:18
<bakkot>
I could generate one but it's best if the speakers do it
02:18
<littledan>
I could generate one but it's best if the speakers do it
when you say "generate", do you mean you'd write it?
02:18
<bakkot>
yes
02:23
<bakkot>
I strongly agree with Michael's point that we should never switch on iterability for any reason other than to throw for non-iterables
02:23
<rbuckton>
auto-wrapping is a footgun that required a special symbol to workaround for Array.prototype.concat. We shouldn't repeat that mistake
02:24
<ljharb>
that isn't why isConcatSpreadable exists, it exists so DOM NodeLists can explain their special array concat behavior
02:25
<keith_miller>
I thought isConcatSpreadable existed to make me suffer as a new hire :P
02:25
<ljharb>
iow that symbol is not relevant to this proposal, whether it autowraps or not
02:25
<rbuckton>
It also likely wouldn't have been necessary if Array.prototype.concat did not have the auto-wrapping behavior
02:25
<ljharb>
that too!
02:25
<ljharb>
someone made sure that "make keith suffer" was redacted from the notes
02:25
<ljharb>
it would still have been necessary.
02:26
<ljharb>
because NodeLists aren't arrays and did have special concat behavior
02:26
<ljharb>
without the autowrapping, NodeLists would have thrown instead of been added without spreading
02:26
<rbuckton>
Either way, auto-wrapping is a footgun. it also doesn't align with our recent decision to cut back on coercing things
02:26
<ljharb>
but NodeLists spread, thus the symbol. nothing to do with autowrapping whatsoever.
02:27
<hax (HE Shi-Jun)>
What's the special behavior of NodeList?
02:29
<hax (HE Shi-Jun)>
Either way, auto-wrapping is a footgun. it also doesn't align with our recent decision to cut back on coercing things
I guess the behavior of Array.p.concat is come from perl. Though perl have the sigil to indicate whether it's a scalar or list.
02:32
<nicolo-ribaudo>
As a committee, we should adopt the principle of "making it hard to accidentally do the wrong thing". When user intention is ambiguous, let's ask users to be explicit
02:33
<littledan>
In TC39, the bare minimum is "web compatibility", which is a much weaker property than "breaking change". As Jordan explained, basically anything that we do can be considered breaking.
02:36
<Bradford Smith>
Iterable helpers that flatten their arguments are implicitly branching on iterability and likely to be used a lot in future.
02:38
<bakkot>
which iterable helpers flatten their arguments?
02:39
<Bradford Smith>
Maybe my memory is faulty. I thought there was at least one API that did this.
02:39
<rbuckton>
IIRC, Iterator.prototype.flatMap does not coerce non-iterator/non-iterable
02:39
<bakkot>
it rejects non-iterators
02:40
<rbuckton>
If you consider Iterator.concat to essentially be (...args) => args.values().flatMap(x => x), then we should also throw for non-iterators
02:41
<ljharb>
in general as well, something being iterable is a massively impactful "trait" of it - something changing between being "a thing" to being "a container of things" isn't and shouldn't be a common thing. if we're talking about good API design, good API design wouldn't make this change, i'd think
02:42
<bakkot>
If you consider Iterator.concat to essentially be (...args) => args.values().flatMap(x => x), then we should also throw for non-iterators
to be really explicit, this proposal only accepts iterables, not iterators
02:42
<bakkot>
accepting iterators turns out to get really awkward
02:42
<bakkot>
because you have to take responsibility for closing them
02:44
<rbuckton>
I'm not saying it must be implemented as such, but a naive implementation using flatMap would throw, not coerce.
02:45
<ljharb>
that naive implementation would eagerly exhaust the iterators, which this doesn't do
02:45
<rbuckton>
Again, I'm talking about consistency. Iterator generally doesn't coerce
02:46
<ljharb>
true, that's what Iterator.from is for
02:46
<rbuckton>
I'm not concerned, there are plenty of bad API designs on Array we shouldn't carry forward, even if we carry forward the concept to other APIs
02:46
<Justin Ridgewell>
@ljharb very weakly yes, but I got over it quickly in Rust
02:47
<Justin Ridgewell>
Used a whole bunch of once(foo), but it’s much easier in JS because you can wrap in an array without screwing with types.
02:47
<rbuckton>
For instance, iterator helper methods don't take a thisArg despite the array prototype methods of the same name doing so.
02:49
<ljharb>
sure, but array concat's behavior isn't bad. (ignoring isConcatSpreadable ofc) the thisArg is useless since arrows and bind exist
02:50
<nicolo-ribaudo>
Rob Palmer If Ron finishes early, you can move forward my import attributes discussion (the constraint on the agenda is mine)
02:50
<Rob Palmer>
Thank you, Nicolo
03:01
<rbuckton>
Rob Palmer with the deadpan "wheee" 😂
03:02
<jkup>
hahahahahahahaha
03:03
<bakkot>
lots of stage 4!
04:00
<Rob Palmer>
The schedule has been updated significantly! Today's afternoon session now looks very different
04:02
<rkirsling>
oh whoa apparently the rap battle is happening today
04:03
<Aki>
GIRD YOUR LOINS EVERYONE
04:16
<yulia>
clarifying question for someone here who probably knows the answer (otherwise when guybedford has time): This proposal is mostly to make worker imports of modules more statically analyzable right? why are new methods necessary on the Module Source object for this? https://tc39.es/proposal-esm-phase-imports/#sec-module-source-objects
04:18
<nicolo-ribaudo>
Yes that was the primary use case, but people then tried to think about how to use this for static analysis (basically exposing the metadata that the engine already has to collect)
04:18
<nicolo-ribaudo>
I think this would mostly be useful in Node.js as it is
04:19
<nicolo-ribaudo>
The browser utility is more marginal, unless we get something like the module constructor
04:19
<shu>
yeah i'm not clear on imports() and exports() utility either
04:19
<yulia>
yeah its a little hard to see a justification for this in browsers right now
04:20
<yulia>
but thats not related to the update, this is a general concern about the proposal
04:20
<nicolo-ribaudo>
Can one of you go on the queue?
04:20
<nicolo-ribaudo>
thanks :)
04:32
<rbuckton>
erights: As stated on a previous slide, there is no return override capability.
04:33
<Mathieu Hofman>
rbuckton: I think Mark's question (who isn't on Matrix) is whether a class can use a struct as the returned object in a return override to stamp fields on the struct
04:33
<rbuckton>
Ah. No, it cannot
04:33
<ljharb>
why not?
04:33
<ljharb>
if it's an object it should work
04:34
<ljharb>
just as if i can weakly hold it
04:34
<Mathieu Hofman>
I mean I'd love that, but yes, why, what's the mechanism ?
04:34
<ljharb>
it's an object. all objects (except window) can have fields stamped on them via return override.
04:34
<rbuckton>
No, the fields must be statically known at construction time for one-shot initialization
04:34
<Mathieu Hofman>
if it's an object it should work
I am very against this line of logic. A WeakMap capability should not be syntactic
04:34
<ljharb>
"adding a private field" is the same as "putting an object in a weakmap"
04:35
<ljharb>
that's explicitly how private fields were designed
04:35
<ljharb>
return override isn't syntactic
04:35
<ljharb>
it is currently an invariant that if it is an object (modulo window) you can stamp private fields onto it via return override, and hold it weakly. we shouldn't break that invariant.
04:35
<Mathieu Hofman>
return override + private field stamping is a syntactic capability that is not deniable or virtualizable, unlike WeakMap
04:36
<ljharb>
that's already the case for all objects, it's a consequence of being an object.
04:36
<rbuckton>
private fields, if/when supported, will also have a fixed layout.
04:36
<Mathieu Hofman>
and it was a huge mistake
04:36
<Mathieu Hofman>
and I strongly believe we should not hold this as an invariant
04:36
<ljharb>
doesn't mean we should create inconsistency by deviating from it
04:36
<rbuckton>
it is necessary to achieve the performance characteristics we want for structs/shared structs
04:36
<ljharb>
to me this is an obstacle to stage 2, to be clear.
04:37
<bakkot>
can you class extends Struct {}? if so you can surely put a private filed in that class?
04:37
<nicolo-ribaudo>
private fields, if/when supported, will also have a fixed layout.
The fixed layout is so that struct methods can "quickly" access them, right? Those installed via return override would not be private fields that belong to the struct, so they wouldn't go through that fast path
04:39
<rbuckton>
Yes and no. The fixed layout is partially so that implementations can properly optimize field accesses in ways that they cannot with normal fields today. For shared structs, we want private fields to be shared memory as well
04:39
<Mathieu Hofman>
That is technically not necessary for for stamping private fields
04:40
<bakkot>
right but... can you do that thing?
04:45
<rbuckton>
can you class extends Struct {}? if so you can surely put a private filed in that class?
We could possibly allow this by storing the private fields of a struct/shared struct differently than those added by a class, where private fields added by a class are more weakmap like, while those added by a shared struct maintain fixed layout to be portable across agents.
04:46
<ljharb>
that sounds like the only option to resolve it tbh
04:46
<bakkot>
I am OK with it being impossible to class extends Struct {}, to be clear
04:46
<bakkot>
just asking if that would work
04:47
<ljharb>
i'm not ok with being unable to stamp fields onto it.
04:47
<rbuckton>
I'd be fine class extends struct not working
04:47
<hax (HE Shi-Jun)>
As the current proposal, struct seems like a weakened version of class. Perceptually, the difference between struct and class is much smaller than the difference between struct and shared struct. I mean, it seems easy to rewrite a class to struct, but very hard to modify a struct to become a shared struct. This make me feel weird that "struct" and "shared struct" use similar name and syntax...
04:48
<bakkot>
if (and only if) it is impossible to class extends Struct {} then I am also ok with the return-override trick not allowing you to return a struct
04:48
<bakkot>
in which case, as a consequence, you could not stamp additional private fields on an existing struct
04:49
<littledan>
Correlation is also important even if you just have one object, and want the methods to work after sharing it to the other side
04:51
<rbuckton>
struct is a restricted form of class, partly because class polymorphism is expensive and slow and cannot be fully optimized via ICs. the fixed layout of structs is partly intended to improve performance due to the well known layout. Basically: class is more flexible but slower, struct is more restrictive but faster.
04:54
<rkirsling>
did I blink and miss an explanation of function coloring
04:55
<rbuckton>
did I blink and miss an explanation of function coloring
Function coloring is a function being aware of whether it is invoked inside of an unsafe block.
04:55
<rkirsling>
I think I understand what it means (like "an async function is fundamentally different from a sync function") but I don't see what shu is saying
04:55
<ljharb>
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
04:55
<rkirsling>
Function coloring is a function being aware of whether it is invoked inside of an unsafe block.
ohhh
04:55
<rkirsling>
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
ooh a Bob post
04:55
<bakkot>
we should add that to the glossary
04:55
<hax (HE Shi-Jun)>
rbuckton: Yeah, I mean it seems we should use syntax like sealed class { } to make it clear (though sealed is not a correct keyword) that it's a better but restricted class. And let shared struct just use struct {} ...
04:56
<ljharb>
the queue has 13 items btw
04:56
<danielrosenwasser>
Basically if you have a function foo that contains an unsafe {} block, callers of foo don't need to wrap it in an unsafe {} block.
04:56
<ljharb>
so i'd be able to write an "am i in an unsafe block" predicate?
04:56
<rbuckton>
rbuckton: Yeah, I mean it seems we should use syntax like sealed class { } to make it clear (though sealed is not a correct keyword) that it's a better but restricted class. And let shared struct just use struct {} ...
Shu and the v8 team have other reasons to want struct, including the unique construction semantics. struct and shared struct construction differs significantly from class.
04:57
<danielrosenwasser>
so i'd be able to write an "am i in an unsafe block" predicate?
oh no
04:57
<rbuckton>
so i'd be able to write an "am i in an unsafe block" predicate?
With function coloring, yes. As specified, no and we do not think it should be added.
04:57
<ljharb>
gotcha thanks
04:57
<danielrosenwasser>
oh no
and by that I mean "ugh yes"
04:57
<Mathieu Hofman>
so i'd be able to write an "am i in an unsafe block" predicate?
as a property access on a proxy, maybe, depending on the open question
04:57
<Mathieu Hofman>
but as a predicate that has the shape of a function, no
04:57
<ljharb>
if you can't write such a predicate i'm not sure how you could virtualize shared structs
04:58
<hax (HE Shi-Jun)>
Shu and the v8 team have other reasons to want struct, including the unique construction semantics. struct and shared struct construction differs significantly from class.
I understand from the engine viewpoint (or spec viewpoint) it's true, but I guess from developer concept model, it's too different.
04:58
<Mathieu Hofman>
you can with proxy
04:58
<ljharb>
ok, then you can, and functions can be colored manually?
04:58
<Mathieu Hofman>
it'd just be a boolean flag passed to the trap
04:59
<hax (HE Shi-Jun)>
I understand from the engine viewpoint (or spec viewpoint) it's true, but I guess from developer concept model, it's too different.
Maybe TG5 could investigate it
04:59
<nicolo-ribaudo>
so i'd be able to write an "am i in an unsafe block" predicate?

You can try/catch around reading from a shared struct that you have, right?

shared struct Test { x }

{
  try { new Test().x } catch { console.log("not unsafe block") }
}

unsafe {
  try { new Test().x; console.log("unsafe block") } catch { }
}
05:00
<rbuckton>
I understand from the engine viewpoint (or spec viewpoint) it's true, but I guess from developer concept model, it's too different.
Even from a developer point of view, the construction semantics of a struct differ enough from class that making it differ purely based on a modifier would trip up developers.
05:00
<ljharb>

You can try/catch around reading from a shared struct that you have, right?

shared struct Test { x }

{
  try { new Test().x } catch { console.log("not unsafe block") }
}

unsafe {
  try { new Test().x; console.log("unsafe block") } catch { }
}
ok, but can i run that try/catch inside a function that someone else invokes in, or not in, an unsafe block?
05:00
<danielrosenwasser>

ah I've misunderstood - so is the following disallowed?

function foo() {
    unsafe {
        bar();
    }
}

function bar(sharedInstance) {
    sharedInstance.property = 123;
}
05:00
<nicolo-ribaudo>
ok, but can i run that try/catch inside a function that someone else invokes in, or not in, an unsafe block?
No, but that function's body is always running in "safe" mode
05:00
<nicolo-ribaudo>
It's like checking if your caller is strict or loose
05:00
<nicolo-ribaudo>
You can't
05:00
<rbuckton>

ah I've misunderstood - so is the following disallowed?

function foo() {
    unsafe {
        bar();
    }
}

function bar(sharedInstance) {
    sharedInstance.property = 123;
}
Yes, this does not work.
05:01
<bakkot>
I would like to see a lot more examples what code is/is not legal for unsafe, somewhere
05:01
<bakkot>
it is probably good I just don't understand it yet
05:01
<rbuckton>
bar does not magically get colored as unsafe when called. it must be lexically scoped within the block.
05:01
<rbuckton>
using or unsafe?
05:01
<bakkot>
unsafe, sorry
05:02
<rbuckton>
unsafe only controls the ability to get/set a field on a shared struct instance, and only applies to code lexically scoped within the unsafe {} block.
05:02
<bakkot>
ok, that sounds straightforward; I think I got confused by all the discussion of coloring
05:02
<Mathieu Hofman>
unsafe only changes the behavior of get/set lexically contained in the block.
05:02
<bakkot>
but I am confused about the discussion of the APIs, then
05:02
<bakkot>
like Reflect.get etc
05:03
<Mathieu Hofman>
Should Reflect.get have some way to access the value (regardless of where the call happens)
05:03
<rbuckton>
The problem with Reflect.get is that it either must always succeed or always throw when reading a shared struct field.
05:03
<bakkot>
or we thread a parameter about unsafe-ness through, per the slides
05:04
<rbuckton>
Which means a Proxy must also either always succeed or always fail, or passing a get through a proxy trap becomes inconsistent when it passes through Reflect.get.
05:04
<rbuckton>
Yes, that's the third option.
05:04
<Mathieu Hofman>
get/set behavior is pretty straightforward. Where it gets funky is with own prop MOPs
05:05
<rbuckton>
My point is more that Reflect.get cannot magically know its in an unsafe block
05:05
<bakkot>
ack
05:06
<rbuckton>
It either must always succeed, always fail, or be explicitly informed via a parameter.
05:11
<danielrosenwasser>
Maybe I'm misunderstanding - but if you view it as an object which has been sealed, the behavior seems consistent with other objects, right?
05:12
<bakkot>
given a choice between "make it practical to write shared-memory parallelism in JS" and "preserve the property about things being in WeakMaps", I cannot imagine thinking the second thing is as important
05:12
<bakkot>
it is like, several orders of magnitude less important
05:16
<bakkot>
this is not to say that I don't see the real cost to having more complex rules for developers. it's just that making it practical for pages to have shared-memory parallelism is of incredible, massive value to every user of the web, measured in nontrivial fractions of our lives spent waiting for slow pages that didn't have to be slow. and against that, "JS developers have more complexity to learn" just does not rate
05:16
<bakkot>
ideally, of course, we would find something that allows us to get both
05:16
<littledan>
Yeah this seems like a clear case of what Yulia mentioned as a philosophical concern
05:17
<bakkot>
but if it comes down to a choice between those two, we cannot choose the "we don't get practical parallelism" one.
05:17
<rbuckton>
I'd much rather have shared memory multithreading than consistency with WeakMap keys. We already have this violation with symbols.
05:17
<ljharb>
symbols aren't objects.
05:19
<rbuckton>
There are other synchronization primitives and concurrency mechanisms we'd like to add, but none meet the bar for an MVP proposal, we hope to propose them as follow-ons later.
05:19
<Mathieu Hofman>
sorry I spoke too quickly, there is currently no spec behavior that allows a host to prevent object keys to be added to WeakMap, but there is to allow them to refuse any private field stamping
05:19
<ljharb>
sorry I spoke too quickly, there is currently no spec behavior that allows a host to prevent object keys to be added to WeakMap, but there is to allow them to refuse any private field stamping
sure but that language was only added recently for window specifically
05:20
<rbuckton>
There is also the possibility that structs and shared structs are more primitive-like than object-like, especially given that shared struct per-realm prototype lookup is likely to be very much like primitive prototype lookup.
05:21
<ljharb>
yes, i remain surprised they're not primitives personally
05:21
<Mathieu Hofman>
primitives shouldn't be mutable
05:21
<ljharb>
oh true
05:21
<ljharb>
Mathieu Hofman: re the host hook, it's only allowed in a web browser https://tc39.es/ecma262/#sec-privatefieldadd and that was very very intentional, since the expectation was that only window would ever use it
05:22
<rkirsling>
I am also worried about this topic but unlike Waldemar, I feel a lack of expertise on the subject lol
05:22
<rbuckton>
In a way, they are essentially "structured primitives" in that they have own fields. I'm not opposed to them having primitive-like behavior for typeof and Object(), but we'd need to discuss more among the champions.
05:22
<Mathieu Hofman>
that would be a much bigger problem for existing programs, a new type that has object like bahviors
05:22
<ljharb>
"use unsafe";
05:22
<rbuckton>
that would be a much bigger problem for existing programs, a new type that has object like bahviors
Record was originally proposed to do this, but I see your point.
05:23
<rkirsling>
"use unsafe";
"extra sloppy";
05:23
<Mathieu Hofman>
right and we only considered it because R/T are immutable
05:23
<bakkot>
the value of unsafe blocks is definitely much lessened if unsafe-ness is not part of the type system. we could make it so, though? in the sense of, functions could be tagged with unsafe-ness, which is on by default if you use unsafe {} blocks, and then have some explicit mechanism for saying "this function uses an unsafe block but is actually safe"
05:24
<bakkot>
and if you call an unsafe function and do not have unsafe {} in your call stack then it throws
05:24
<bakkot>
disclaimer, I have not thought about this idea for more than 30 seconds
05:25
<rkirsling>
one concern that immediately rises in my mind (thinking about the cross-language use of an unsafe keyword) is:
is this the only thing we'd ever want unsafe to mean in JS?
05:25
<rbuckton>
and if you call an unsafe function and do not have unsafe {} in your call stack then it throws
This becomes function coloring, which makes things even more complicated.
05:25
<shu>
yeah other names have been proposed, like volatile, i think?
05:25
<bakkot>
yes, but with a way to opt-out, which matters a lot
05:25
<shu>
re: "unsafe"
05:25
<bakkot>
the reason async is annoying is because you can't go from async to sync
05:25
<bakkot>
and here you could
05:25
<Mathieu Hofman>
and if you call an unsafe function and do not have unsafe {} in your call stack then it throws
you're describing function coloring
05:26
<rbuckton>
unsafe {} isn't necessary at all for shared memory semantics, it is purely a guardrail to discourage unintended misuse
05:27
<bakkot>
function coloring is annoying only because you can't use async from sync. here you could as long as you explicitly opt in to enforcing the invariants yourself.
05:27
<rkirsling>
I do like volatile, maybe. either way I'm glad to hear that naming is being thought of
05:27
<rbuckton>
yeah other names have been proposed, like volatile, i think?
Yes, volatile {} was a suggestion from the TypeScript team as an alternative, and we're welcome to discussing others if there is a better option.
05:27
<Bradford Smith>
Personal take: The benefit of private fields is guaranteed encapsulation. I see the reverse WeakMap used to implement it to be an unfortunate implementation detail, not something to take advantage of. I would expect and hope that 99% of developers will not even be aware of it. Given that, it would be really weird if you could add private fields to structs after construction - which are supposed to be of a fixed shape.
05:27
<Mathieu Hofman>
You also basically end up with a 1 bit dynamic scoping for unsafeness of the call
05:30
<rbuckton>
ljharb: (a) is mostly figured out amongst the stakeholders, and we believe (b), (c), and (d) will not significantly impact whether this proposal will advance beyond stage 2. (b) could obviously have some limitations in the long term.
05:31
<nicolo-ribaudo>
What does "contamination" mean in this case? Isn't it solved by "no function coloring"?
05:31
<rbuckton>
I don't understand what "contamination" means here
05:31
<rbuckton>
unsafe is very local, it doesn't spread virally like async/await.
05:31
<Justin Ridgewell>
Does it need to be unsafe blocks?
05:32
<Justin Ridgewell>
Could it be Reflect.getUnsafe() and have it be explicit accesses without carrying a bit throughout the spec and ecosystem
05:32
<danielrosenwasser>
Is accessor allowed in a shared struct? Can I just avoid unsafe with that?
05:33
<rbuckton>
That level of indirection would be a major performance bottleneck for a performance-critical feature.
05:34
<rbuckton>
That level of indirection would be a major performance bottleneck for a performance-critical feature.
This was in response to Reflect.getUnsafe()
05:34
<rkirsling>
I don't feel like it's that rare for a Stage 2 proposal to die...?
05:34
<rkirsling>
am I crazy
05:34
<Mathieu Hofman>
R/T comes to mind
05:35
<rkirsling>
I don't want R/T to be dead though 😭
05:35
<bakkot>
i gotta say, given that we can already do sharedArrayBuffer[0] = 42 wherever we want, I really do not understand the hard constraint of unsafe blocks from mark
05:36
<bakkot>
like, yes, it would be nice to have some help from the language to call out when there's spooky stuff happening
05:36
<bakkot>
but we already do not have that
05:36
<ljharb>
then convince the browsers to make new primitives (ie, convince that the adoption and value will be sufficient to be worth the work)
05:36
<Justin Ridgewell>
This was in response to Reflect.getUnsafe()
How is it a level of indirection, this can be optimized the same as foo.bar
05:36
<yulia>
congrats on stage 2 shu
05:37
<shu>
thank you but why am i so unhappy
05:37
<Mathieu Hofman>
i gotta say, given that we can already do sharedArrayBuffer[0] = 42 wherever we want, I really do not understand the hard constraint of unsafe blocks from mark
object access with different kind of values is very different in usage from a SAB, which may be denied from the environment (API not syntax)
05:37
<rkirsling>
thank you but why am i so unhappy
"snapshots of TC39"
05:37
<yulia>
thank you but why am i so unhappy
yeah that was a rough one, but i believe the landscape is workable
05:37
<yulia>
and shared memory will happen, having support for it in JS is important and this is the right shape
05:37
<rbuckton>
How is it a level of indirection, this can be optimized the same as foo.bar
Even if it can, I don't really want to write Reflect.getUnsafe(Reflect.getUnsafe(x, "y"), "z") on a regular basis, that's terrible DX.
05:37
<bakkot>
I am OK with making these deniable in the environment, if that's the concern? have like a SharedStruct which every shared struct needs to extend and which can be deleted
05:38
<shu>
oh i didn't think about that as a way to deny syntax, that's interesting
05:38
<bakkot>
does that solve the problem for you?
05:38
<rbuckton>
I am OK with making these deniable in the environment, if that's the concern? have like a SharedStruct which every shared struct needs to extend and which can be deleted
In the stakeholders call we have discussed deniability in the environment just being that you can't actually share the value across agents.
05:38
<Justin Ridgewell>
Even if it can, I don't really want to write Reflect.getUnsafe(Reflect.getUnsafe(x, "y"), "z") on a regular basis, that's terrible DX.
I don’t really wanna write unsafe {} everywhere either
05:39
<bakkot>
or just like when a shared struct is evaluated it checks globalThis.canMakeSharedStructs and then if you want to turn that off you make that nonwritable-nonconfigurable false
05:39
<rbuckton>
I don’t really wanna write unsafe {} everywhere either
Neither do I, but its far more convenient than Reflect.getUnsafe().
05:39
<bakkot>
or... several other options
05:39
<ljharb>
laughs in python's GIL
05:39
<bakkot>
denying postMessage and similar sharing-across-agent capabilities works just as well, yes
05:39
<yulia>
can we do unsafe functionName () {} and just make it like async/await? (not a serious suggestion)
05:40
<Justin Ridgewell>
Neither do I, but its far more convenient than Reflect.getUnsafe().
We need JSSugar to automatically transpile gets/sets into getUnsafe()
05:40
<bakkot>
(anyway I really really gotta go to sleep, will read messages in the morning and leave transcription bot running for now, later all)
05:40
<rbuckton>
can we do unsafe functionName () {} and just make it like async/await? (not a serious suggestion)
I did propose this, but not like async/await, more as a way to avoid doubly nested blocks. Alternatively, function foo() unsafe {}
05:40
<rbuckton>
Keep in mind that unlike async/await, unsafe does not spread virally to your callers
05:41
<ljharb>
i mean, async/await doesn't directly do that either
05:41
<ljharb>
only indirectly by returning a promise
05:41
<yulia>
async/await results in very viscous refactoring situations
05:41
<littledan>
I think it’s good that our process allows significant questions to be open during Stage 2. It would be bad if champions were incentivized to hide debates until later. But more importantly, the signal to invest significantly in a proposal is important to be able to dedicate the work to solve the problem.
05:41
<rbuckton>
i mean, async/await doesn't directly do that either
In any meaningful way, it does.
05:41
<yulia>
you have to update all callers, or end up with a fire and forget situation
05:41
<Justin Ridgewell>
I did propose this, but not like async/await, more as a way to avoid doubly nested blocks. Alternatively, function foo() unsafe {}
Is @waldemar's concern that unsafe exists as a concept, or that it’s implemented as a block?
05:41
<yulia>
so yeah unsafe would not be that viscuous
05:41
<Justin Ridgewell>
If the second, then unsafe functions don’t really solve it.
05:42
<waldemar>
I don't understand what "contamination" means here
unsafe will contaminate generic abstractions and algorithms, which will be pressured to wrap themselves inside unsafe blocks just so that folks can pass shared structs into them. Most don't really care about consistency and we already have the same problem with accessors, callbacs, and proxies. Wrapping one of these in unsafe will just become boilerplate practice.
05:42
<yulia>
the function solution would be implemented the same way as the block, and would have the same complexity concern i had earlier, which is why i wasn't so serious with it
05:43
<yulia>
so its not really a solution, we would need something else, that doesn't require marking the get/set with a flag
05:43
<shu>
waldemar: yulia: Mathieu Hofman (i can't find mark in this channel) ljharb PTAL at the conclusions in the notes to see if it's explicit enough for your liking
05:43
<rbuckton>
unsafe will contaminate generic abstractions and algorithms, which will be pressured to wrap themselves inside unsafe blocks just so that folks can pass shared structs into them. Most don't really care about consistency and we already have the same problem with accessors, callbacs, and proxies. Wrapping one of these in unsafe will just become boilerplate practice.
shared memory multithreading is more of a power-user feature, I doubt every npm package is going to start enclosing their sources in unsafe {} at the top level as a workaround. That's just bad practice.
05:44
<rbuckton>
And it should be discouraged.
05:44
<Mathieu Hofman>
unsafe will contaminate generic abstractions and algorithms, which will be pressured to wrap themselves inside unsafe blocks just so that folks can pass shared structs into them. Most don't really care about consistency and we already have the same problem with accessors, callbacs, and proxies. Wrapping one of these in unsafe will just become boilerplate practice.
But generic abstractions and algorithms shouldn't be unsafely dealing with shared structs, that's the point. They are likely not able to operate generically on the object.
05:45
<rbuckton>
I would encourage anyone who has interest or concerns in the shared structs proposal to join our regularly scheduled stakeholders calls, we've been making a lot of positive progress in all areas.
05:46
<waldemar>
We have no viable story for how to handle abstractions that apply to shared structs.
05:47
<waldemar>
How do you tell an abstraction that can apply to both shared and unshared structs that this usage is safe and that usage is unsafe?
05:48
<Mathieu Hofman>
To be honest the only thing I can think of (besides unsafe blocks) to enable correct shared fields access is to only allow private shared fields, which would require methods / accessors
05:49
<ljharb>
that would give you immutable structs right out of the gate, no?
05:49
<shu>
I would encourage anyone who has interest or concerns in the shared structs proposal to join our regularly scheduled stakeholders calls, we've been making a lot of positive progress in all areas.
important to call this out ^^
05:49
<Mathieu Hofman>
How do you tell an abstraction that can apply to both shared and unshared structs that this usage is safe and that usage is unsafe?
What abstractions do you imagine can safely but non explicitly deal with shared memory access ?
05:49
<waldemar>
But generic abstractions and algorithms shouldn't be unsafely dealing with shared structs, that's the point. They are likely not able to operate generically on the object.
Many, if not most, can and should. Almost the same problem already arises with getters, setters, proxies, callbacks mutating state, etc.
05:49
<rbuckton>
that would give you immutable structs right out of the gate, no?
"immutable" if you squint hard.
05:49
<shu>
reading the back log, i agree with Mathieu Hofman that return override w/ private field stamping really really should not rise to the level of a design invariant that consciously aim to keep
05:50
<ljharb>
"immutable" if you squint hard.
lol i mean, a shared struct with no setters, then, would be immutable from without at least?
05:50
<rbuckton>
Yes, I picked up on that.
05:50
<waldemar>
In practice there is very little delta between the mischief shared objects can get into and what ordinary callbacks, accessors, proxies, etc. can do.
05:51
<waldemar>
The differences are primarily of interest to experts, not casual users.
05:51
<shu>
In practice there is very little delta between the mischief shared objects can get into and what ordinary callbacks, accessors, proxies, etc. can do.
i agree, but i also don't know how to address mark's requirement that the app-wide opt-in/out switch like COOP/COEP is insufficient
05:52
<Mathieu Hofman>
yet somehow shared memory programs have a lot more race type bugs than async or callback code
05:52
<waldemar>
i agree, but i also don't know how to address mark's requirement that the app-wide opt-in/out switch like COOP/COEP is insufficient
I don't either.
05:52
<waldemar>
yet somehow shared memory programs have a lot more race type bugs than async or callback code
They do. Unsafe blocks won't fix that.
05:52
<rbuckton>
I'd rather not have unsafe {}, to be honest. But I'd rather have unsafe {} if that means we can get usable shared memory multithreading. I'm open to other suggestions so long as they don't negatively impact performance in a meaningful way.
05:53
<shu>
though i don't think we've fully engaged with bakkot's idea that there be a programmatic way to deny shared structs, even if they're syntax?
05:56
<rbuckton>
Given that JS has proxies and getters, any property access could conceivably change underneath you.
05:56
<shu>
waldemar: is it a fair characterization to say your skepticism of unsafe {} boils down to SABs already must be grandfathered in, so it's a false guardrail?
05:56
<shu>
  • what you said about getters/setters/proxies etc
05:56
<shu>
wtf is wrong with matrix
05:56
<rbuckton>
Also, its possible to write abstractions that work with shared and unshared objects equally, so long as they do so through callbacks since those callbacks can be lexically scoped within an unsafe {} block.
05:56
<shu>
if i start a message with a + it turns it into a - and then a bullet point??
05:57
<ryzokuken>
wtf is wrong with matrix
markdown
05:57
<yulia>
though i don't think we've fully engaged with bakkot's idea that there be a programmatic way to deny shared structs, even if they're syntax?
yeah im interested in this can we expand on it?
05:58
<shu>
i'm not sure if it actually addresses agoric's concerns though, should ask
06:03
<waldemar>
waldemar: is it a fair characterization to say your skepticism of unsafe {} boils down to SABs already must be grandfathered in, so it's a false guardrail?

That's part of it. A bigger part is that:

  • unsafe blocks will contaminate generic code merely because someone wants to use it with shared structs
  • we don't have a story for how to indicate which user API calls are safe and which are unsafe, so it's a false guardrail.
06:03
<Mathieu Hofman>
Mark is there with you, time to chat with him ;)
06:05
<nicolo-ribaudo>
How does unsafe work in Rust? I know that it's a different type of unsafe, but I assume some of the same concerns about "virality" and "false guardrail" still apply?
06:06
<rbuckton>
Rust has a borrow checker and full type system, so it can enforce the guardrail via the API
06:07
<rbuckton>
In JS, we have "name your function fooUnsafe()"
06:07
<nicolo-ribaudo>
Re the "everybody would use unsafe just to be sure", maybe instead of unsafe we can use a different property access operator. e.g. obj.foo only works for non-shared objects, and obj⚠️.foo would only work for shared structs
06:08
<nicolo-ribaudo>
So you cannot use it "just in case", and if you want to write code that works with both you have to introduce your own abstractions
06:10
<nicolo-ribaudo>
In JS, we have "name your function fooUnsafe()"
This seems to be an argument for actually introducing "unsafe functions", and making it a new colour
06:11
<danielrosenwasser>

From here:

To switch to unsafe Rust, use the unsafe keyword and then start a new block that holds the unsafe code. You can take five actions in unsafe Rust that you can’t in safe Rust, which we call unsafe superpowers. Those superpowers include the ability to:

  • Dereference a raw pointer
  • Call an unsafe function or method
  • Access or modify a mutable static variable
  • Implement an unsafe trait
  • Access fields of a union

So my understanding is that basically the operations allowed in an unsafe expression context are:

  • Dereference a raw pointer
  • Access or modify a mutable static variable
  • Call an unsafe function or method
  • Access fields of a union

The other two are basically markers at the declaration site, and they push the work onto the caller to either contain the code in an unsafe block, or mark the containing function as unsafe. Because you have both options, function coloring isn't mandatory.

06:13
<nicolo-ribaudo>
It sounds much more similar to the one proposed for shared structs than I expected! "Access fields of a union" is kinda like our use case, even if it's unsafe for different reasons
06:13
<nicolo-ribaudo>
But the difference is that whether you need unsafe or not is not determined by your caller, because as Ron said there is a type checker
06:17
<rkirsling>
now entering the spice zone
06:17
<rkirsling>
super appreciative of that disclaimer actually
06:17
<Chris de Almeida>
the first rule of spice club...
06:18
<Ben>
everyone, please, it is crucial to walk without rhythm while in the spice zone
06:29
<nicolo-ribaudo>
I'm curious about that logical assignment CVE
06:30
<nicolo-ribaudo>
Isn't it something that can be implemented just in the bytecode emitter, relying on existing ops?
06:30
<rkirsling>
I looked that one up too because it blew my mind
06:30
<Michael Ficarra>
I want to know what portion of these CVEs would have been impossible had they been implemented in a memory safe language
06:30
<rkirsling>
it was specific to SM's initial implementation
06:30
<ljharb>
I want to know what portion of these CVEs would have been impossible had they been implemented in a memory safe language
esp given the v8 team's pushback to openssf on switching to one
06:31
<Michael Ficarra>
Obviously "more C++ code" means "more memory bugs". That does not mean we should do less language development. It means that we should write less C++ code.
06:31
<yulia>
I want to know what portion of these CVEs would have been impossible had they been implemented in a memory safe language
We tried implementing the parser in rust, but ran into performance issues
06:32
<yulia>
rust isn't as heavily optimized yet, and also certain areas of the engine such as garbage collection don't really work in rust
06:32
<nicolo-ribaudo>
Maybe we could just write engines in JS and compile them to native with Porffor
06:32
<Michael Ficarra>
oh I didn't realise performance was more important than security
06:32
<yulia>
if it wasn't a balance, we would not have jits.
06:33
<ryzokuken>
Maybe we could just write engines in JS and compile them to native with Porffor
I mean if this isn't Torque idk what is
06:35
<yulia>
we are trying to approach this in an open way, so that we can come to a solution together. The vast majority of monetary investment, in making JS work, is on implementers shoulders. As is the risk, and responsibility when things go wrong. Being told to stop complaining and that our concerns are invalid is not a way forward. We, as equal delegates, can just say no to all features going forward. We aren't doing that, instead we are inviting dialogue.
06:35
<yulia>
also, JSSugar is one solution, coming from v8 -- not all of the vendors are aligned on it
06:36
<yulia>
I personally see another way forward, tackling a different surface, that will enable language evolution
06:36
<Michael Ficarra>
Oh totally agreed, and I'm actually really supportive of the JSSugar approach. I just don't buy the security motivation basically at all.
06:37
<Andreu Botella (at TC39, 🕐 JST)>
browser vendors aren't the only implementers
06:37
<yulia>
I didn't speak of browsers, but implementers. Moddable is a cosigner
06:38
<Michael Ficarra>
And I'm also really bitter that browsers (and OS vendors) continue to write more code in a memory-unsafe language that I have to run on my computer.
06:39
<yulia>
well, if we make some really radical moves maybe we can make it more feasible to do 1) more of the language in memory safe languages regardless of the browser engine, and 2) allow more competitors
06:39
<yulia>
let's talk about it after because its a big idea that won't be discussed now (im still talking to stakeholders about it)
06:40
<Andreu Botella (at TC39, 🕐 JST)>
I didn't speak of browsers, but implementers. Moddable is a cosigner
Okay, I meant vendors, not specifically browser vendors. Igalia is an implementer who works on engines built by other vendors. Although we're probably in a unique position
06:40
<yulia>
some parts, at least at present (GC in particular) aren't feasible (right now) in a safe language, just because of what you are doing
06:41
<rkirsling>
Okay, I meant vendors, not specifically browser vendors. Igalia is an implementer who works on engines built by other vendors. Although we're probably in a unique position
hey, I co-signed as a JSC implementer from Sony ;)
06:41
<Marja Hölttä>
Michael Ficarra: the most chrome / v8 bugs are not because our C++ is doing memory management wrong, they are because we have a logic bug in generating machine code or because our invariants are extremely complex and one part might make a change which violates an invariant somewhere else. happy to talk more about this. interestingly, a huge proportion of the CVEs listed on shu's slide were in my code, and none of my bugs were because of C++, and would've happened even if V8 was written in a memory safe language.
06:42
<yulia>
also part of the context here is the unshippability of the things that we spec, see my upcoming presentation on species
06:42
<yulia>
species being one of the worst offenders from a sec perspective
06:42
<yulia>
and performance perspective
06:42
<Marja Hölttä>
the basic problem being: "logic bug in a normal application -> typically a bug, not a security issue" whereas "logic bug in a compiler -> a security bug"
06:43
<keith_miller>
100% agreed almost none of them are out of bounds memory accesses. Some of them are UAFs but most memory safe languages wouldn't solve those ones as they're GC related.
06:43
<Michael Ficarra>
also part of the context here is the unshippability of the things that we spec, see my upcoming presentation on species
Do you think that's something we still risk today with our current stage process?
06:44
<keith_miller>
For the most part they're because generated machine code is just wrong
06:44
<yulia>
Do you think that's something we still risk today with our current stage process?
yes, as bigint went through the process, and it is one of the other major offenders
06:44
<Michael Ficarra>
okay then maybe JITs are the real evil
06:44
<keith_miller>
So you'd have to have a proof-carrying compiler, which is, AFAIK, still mostly in academia only
06:45
<yulia>
no disagreement that the performance requirements of the web also drive complexity
06:45
<rkirsling>
okay then maybe JITs are the real evil
a necessary, ingenious sort of evil, yeah
06:45
<yulia>
however, moddable which has a much simpler implementation has also had similar issues. it is not browser/jit only
06:45
<canadahonk>
So you'd have to have a proof-carrying compiler, which is, AFAIK, still mostly in academia only
something something wasm kind of somewhat does this?
06:45
<rkirsling>
(we have JIT totally disabled on PS for security reasons)
06:46
<keith_miller>
something something wasm kind of somewhat does this?
No, it passes it off to the wasm runtime
06:46
<rkirsling>
(it was a HUGE attack surface on PS4)
06:46
<Michael Ficarra>
@keith_miller yeah but it's a much smaller language at that point
06:47
<Michael Ficarra>
(it was a HUGE attack surface on PS4)
I want to see your PS4 threat model. Who is the adversary? Games publishers?
06:47
<ryzokuken>
crackers maybe?
06:47
<rkirsling>
I am not a security expert
06:47
<rkirsling>
I just know that there were whole twitter accounts dedicated to it
06:48
<Rob Palmer>
I assume this slide on "The bar" is a logical OR rather than AND
06:49
<canadahonk>
(we have JIT totally disabled on PS for security reasons)
(this is one of the use-cases for porffor btw ;))
06:49
<nicolo-ribaudo>
Rob it's the implication symbol
07:01
<hax (HE Shi-Jun)>
I lost connection and after reconnect I can't see the shared screen, does anyone have similar issue?
07:01
<jkup>
This happened to me earlier but after a minute I could see it again
07:02
<hax (HE Shi-Jun)>
This happened to me earlier but after a minute I could see it again
thank u, so let me wait a minute :P
07:02
<hax (HE Shi-Jun)>
yeah, it comes back
07:07
<hax (HE Shi-Jun)>
I guess runtimes can bake it, eg. deno/nodejs?
07:09
<nicolo-ribaudo>
Yeah, I would hope we wouldn't make it illegal to implement JSSugar in engines, just optional
07:11
<yulia>
waldemar: sorry i couldn't respond fast enough: the problem statement is very broad, and we so far haven't addressed the point that you made, so if you have any ideas on this they are very very welcome
07:11
<yulia>
maybe we can talk async about it
07:13
<waldemar>
I'm unhappy about the framing of this as a tension between users, developers, and implementors. In most cases we can reduce complexity for all three; existing complexity is a result of past decisions that benefited none of these three.
07:15
<Chris de Almeida>
I'm trying to keep an open mind, but at the end of the day this forks the language and I would just not use the sugar features. yes people use tooling but not exclusively all the time, and a lot of workflows rely on the language being available directly in the browser
07:16
<yulia>
I'm unhappy about the framing of this as a tension between users, developers, and implementors. In most cases we can reduce complexity for all three; existing complexity is a result of past decisions that benefited none of these three.
thats certainly the case for something like species, but bigint is an independent proposal that had a similar effect
07:16
<canadahonk>
I'm unhappy about the framing of this as a tension between users, developers, and implementors. In most cases we can reduce complexity for all three; existing complexity is a result of past decisions that benefited none of these three.
yeah I think the (probably unintended) us vs them framing of the slides is my biggest problem with it personally
07:16
<yulia>
On the other hand, something like nullish coallescing resulted in more efficient code in the end, but (for firefox) we had users who suffered from stability (in particular we had bugs coming in from users who could no longer load sites, but also couldn't update their browser)
07:17
<yulia>
this is because syntax in particular is not forward compatible. you can't shim it, you have to transpile it.
07:18
<waldemar>
thats certainly the case for something like species, but bigint is an independent proposal that had a similar effect
A lot of folks are making points about low BigInt usage, but we'd be hurting if something like that weren't in the language — it comes up rarely in APIs, but, when it does come up, hacking around the lack of BigInt would have made a bigger mess.
07:18
<rbuckton>
pipeline desugaring is a bad example because it's so dead simple
07:19
<Michael Ficarra>
A lot of folks are making points about low BigInt usage, but we'd be hurting if something like that weren't in the language — it comes up rarely in APIs, but, when it does come up, hacking around the lack of BigInt would have made a bigger mess.
Right, it's a coordination point, and the language is the responsible party for providing those.
07:19
<rbuckton>
x = a |> b(%) |> %.c()

is just

var _;
x = (_ = a, _ = b(_), _.c());
07:19
<Mathieu Hofman>
we use BigInt a LOT
07:19
<yulia>
A lot of folks are making points about low BigInt usage, but we'd be hurting if something like that weren't in the language — it comes up rarely in APIs, but, when it does come up, hacking around the lack of BigInt would have made a bigger mess.
this is certainly a benefit for a developer who is using BigInt, ideally you would only pay the price of the features you use
07:19
<yulia>
and i think there is a future where we could have that
07:19
<Mathieu Hofman>
I don't think any financial application could work without BigInt
07:20
<nicolo-ribaudo>
this is because syntax in particular is not forward compatible. you can't shim it, you have to transpile it.
How is this relevant? Those websites would have broken even if there was a missing runtime API. The developer would have still chosen to ship the polyfill for that browser version, similarly to how they could have shipped with the transpiled code
07:20
<rbuckton>
BigInt is also quite important to Azure
07:20
<Michael Ficarra>
I don't think any financial application could work without BigInt
that's a really broad statement
07:21
<Mathieu Hofman>
maybe it's not seen in the instrumentation of browsers, but there are a lot of backend use cases for BigInt
07:21
<yulia>
How is this relevant? Those websites would have broken even if there was a missing runtime API. The developer would have still chosen to ship the polyfill for that browser version, similarly to how they could have shipped with the transpiled code
shims are lightweight to ship, you can't ship a shim for syntax. it requires tooling, shims don't
07:22
<nicolo-ribaudo>
shims are lightweight to ship, you can't ship a shim for syntax. it requires tooling, shims don't
This presentation is based on the assumption that tooling is required anyway
07:22
<yulia>
the second half is, yes
07:22
<nicolo-ribaudo>
Oh, I'll be curious to hear the Mozilla proposed solution when it's ready
07:23
<yulia>
but that is v8's position, mozilla didn't co-sign that
07:23
<yulia>
not that JSSugar isn't a potential solution, we are just unsure about it
07:23
<ljharb>
thats certainly the case for something like species, but bigint is an independent proposal that had a similar effect
imo the reason bigint didn't get adoption is because it's not smoothly interoperable with Number, and thus only devs with bigint-specific use cases use bigints. which isn't many.
07:23
<yulia>
I'm working on getting the approval for it & roping in all of the stake holders, should come soon
07:23
<Chris de Almeida>
I don't have data to support this, but I really think the presentation overestimates the use of build/compilation tooling, and disregards the abundance of... not using those things, or in the same way
07:23
<rbuckton>
Tooling can't address eval, new Function, other evaluators, or new RegExp() which would need the tooling to be run in browser to support these transformations.
07:24
<rbuckton>
It's already a problem when transpiling today.
07:25
<rkirsling>
I don't have data to support this, but I really think the presentation overestimates the use of build/compilation tooling, and disregards the abundance of... not using those things, or in the same way
I would say that'd be my focal point of disagreement with the proposed solution
07:25
<rkirsling>
...as a co-signer of the first half
07:26
<Michael Ficarra>
Tooling can't address eval, new Function, other evaluators, or new RegExp() which would need the tooling to be run in browser to support these transformations.
please don't do these things
07:27
<rbuckton>
please don't do these things
Would you be fine with RegExp syntax that works for /.../ but not new RegExp("...")?
07:28
<Michael Ficarra>
I don't really care either way about regexp. Don't use eval or Function.
07:28
<rbuckton>
And the eval case was an important discussion point re: decorators raised by Mark Miller, so it's come up before in plenary.
07:28
<canadahonk>
... and eval(...) differing completely in support feels 🥴
07:29
<Rob Palmer>
I don't have data to support this, but I really think the presentation overestimates the use of build/compilation tooling, and disregards the abundance of... not using those things, or in the same way
The nuance that I feel like I've never managed to successfully communicate is that tooling is a spectrum but we usually frame it as a dichotomy. Even folk that can't go tool-free benefit from tool-lite. It's also about the % of scenarios that benefit from a % of features working tool-free.
07:31
<rbuckton>
... and eval(...) differing completely in support feels 🥴

You can sort of make it work, but it requires knowing the intricacies of the language. e.g., transpiling

@decorator
class C {
}

and expecting eval(C.toString()) to produce the same result won't work, but

function f() {
  @decorator
  class C {
  }
  return C;
}

and eval(f.toString())() would purely because the function body would capture the entire transpiled result. It's a mess, so definitely not recommended.

07:33
<nicolo-ribaudo>
Node.js shipping a TS compiler is the proof that people hate using tooling
07:33
<Chengzhong Wu>
"Many people using tools" doesn't mean that "many people like using tools"
07:35
<rbuckton>
Node.js shipping a TS compiler is the proof that people hate using tooling
NodeJS would also like other TS features to come to JS so transpiling is less necessary (enum, parameter properties, etc.)
07:37
<littledan>
Yulia: Wasm is in scope for source maps. Considering other serializations is as well, though the group has decided so far that this type of efficiency isn’t the most pressing concern.
07:38
<yulia>
Source maps is just too heavy. it doesn't scale. WASM was using dwarf but there were issues with that as well (i believe for supporting all languages)
07:38
<Rob Palmer>
Node.js shipping a TS compiler is the proof that people hate using tooling

I would use a weaker word than "hate".

It's more about the hierarchy of abstractions - ideas > design patterns > tools > runtimes > language. The more fundamental/essential the functionality, the more folk benefit from pushing it down the hierarchy to codify it and make it more accessible. Folk like types being even more accessible.

07:38
<yulia>
I think that the current source maps group doesn't have any overlap with the WASM debugging wg, but the issue of debugging information in JS was part of that as well
07:39
<littledan>
We are definitely focusing on the mapping to Wasm from source maps. Are there any participants from the previous effort that we should recruit to join?
07:39
<yulia>
have you had fitzgen come by at all?
07:40
<yulia>
I don't know if he will have time but he was on both
07:41
<rbuckton>
Many if not most syntax proposals will require runtime functionality to work. using requires Symbol.dispose, pattern matching requires Symbol.customMatcher as methods on a number of built-ins, so a single feature requires changes to both JS0 and JSSugar.
07:44
<jkup>
Nope, not to any of our recent meetings at least! Would love it if he had time. For Wasm the effort has mostly been lead by Kotlin, Chrome DevTools and Tauri so far.
07:45
<keith_miller>
Why couldn't using be desuggared? Symbol.dispose ??= Symbol() would be the init sequence for the shared symbol
07:45
<yulia>
So if you didn't have the history: we tried to standardize source maps before. That is what became the wasm debugging group
07:46
<rbuckton>
That's not the same as a built-in symbol, plus the using proposal has other API changes as well.
07:46
<jkup>
So if you didn't have the history: we tried to standardize source maps before. That is what became the wasm debugging group
Is this the group? https://github.com/WebAssembly/debugging (trying to catch up on the history here)
07:46
<yulia>
i'll see if i can get fitzgen to come, ill try to come by as well
07:46
<yulia>
yes thats it
07:46
<rbuckton>
TS will downlevel using, but expects the developer to supply the shim for runtime functionality.
07:46
<yulia>
it fell apart (maybe it started up again?), it was mostly chrome that had time for it. yury on the sm team also has some of the history
07:47
<rbuckton>
using may be a trivial example, but pattern matching is not.
07:47
<ljharb>
that's a really good point. if eslint doesn't support syntax by default then users won't adopt it; if it's going to change, eslint won't support it
07:47
<hax (HE Shi-Jun)>
nicolo-ribaudo: I think we can cover Babel cost by forcing champion implement it in Babel 😉
07:48
<rkirsling>
the problem there is that Babel would become a singular blessed tool
07:48
<Michael Ficarra>
set up GoFundMes for TC39 proposals
07:50
<Michael Ficarra>
or just get the community to pay Igalia I guess
07:51
<shu>
the cost isn't in implementation
07:51
<shu>
the cost is maintenance in perpetuity
07:52
<ljharb>
given the current state of voluntary payments to "free" software projects that are important to society/security/humans, i'm not optimistic about browser crowdfunding either
07:53
<nicolo-ribaudo>
shu I understand that you don't want to "demote" any proposal, but it would be a good exercise to pretend that this presentation happened 5-10 years ago, and show how the current proposals would have evolved under this framing
07:53
<shu>
are you asking me to actively invite psychic damage to myself
07:54
<nicolo-ribaudo>
It's part of the cost of proposing such a big change :P
07:55
<hax (HE Shi-Jun)>
the problem there is that Babel would become a singular blessed tool
So let's just ask champions to implement it in at least 2 or 3 or 4 tools as the requirements of stage 3?😅
07:56
<Justin Ridgewell>
Does Mozilla not have someone attending TG2 meetings?
07:57
<ryzokuken>
Does Mozilla not have someone attending TG2 meetings?
they do
07:59
<linusg>
maybe it's not seen in the instrumentation of browsers, but there are a lot of backend use cases for BigInt
Is there bigint instrumentation in browsers? I looked on chromestatus.com/metrics earlier and it doesn't seem to have any related counters
08:04
<rbuckton>
Is bit math still slower on BigInt compared Number? I've wanted to switch to bigint for some of our flags in the TS compiler, but we only recently changed our minimum target to one that supports bigint natively.
08:08
<Mathieu Hofman>
Tooling can't address eval, new Function, other evaluators, or new RegExp() which would need the tooling to be run in browser to support these transformations.
That was a point I wanted to raise on the queue. That or somehow admit that any dynamically evaluated code will have to be compiled ahead of time.
08:09
<Chris de Almeida>
shu: yulia I captured the queue for JSSugar. do you want a continuation if we have time later?
08:09
<yulia>
I've already spoken with them, they are fine with it. But due to issues brought up from other parts of the web platform, regarding what TG2 has been standardizing, we are under heavier scrutiny. So, i'm just double checking with our internal stake holders.
08:11
<Mathieu Hofman>
I don't really care either way about regexp. Don't use eval or Function.
eval is not evil. there are ways to safely evaluate untrusted code.
08:11
<rbuckton>
eval is not evil. there are ways to safely evaluate untrusted code.
In a sandbox, out of process, on another machine...
08:12
<shu>
shu: yulia I captured the queue for JSSugar. do you want a continuation if we have time later?
sure, i want people to say their piece
08:13
<yulia>
I also reacted before seeing the issues, they look really minor
08:14
<yulia>
i honestly can't stress enough how having more time to review would help...
08:14
<nicolo-ribaudo>
I get excited whenever I see well organized data
08:14
<Ashley Claymore>
Maybe that proposal would have been split in two in the same way? Browsers initially only implement the Symbol and add implementations of the methods to the right web APIs. But the syntax part stays at JSSugar (at least initially)
08:15
<Ashley Claymore>
And then in the future Browsers implement the syntax part too when it's the right time for that to happen
08:15
<Chris de Almeida>
this is really cool... I know it's been a long day but... 👀
08:16
<ljharb>
i'm also excited about the possibility of creating a polyfill for API things on-the-fly using es-abstract, so you can get an in-editor REPL for your spec change
08:17
<Mathieu Hofman>
In a sandbox, out of process, on another machine...
no in the same process, either different realm (ShadowRealm) or even same realm (Compartment in hardened Realm). Salesforce uses realms, we use Compartments in production, and Moddable uses compartments too in their devices. Let's not claim there is no way to securely run 3rd party JS in the same process
08:18
<shu>
https://github.com/tc39/Reflector/issues/539
08:19
<rbuckton>
no in the same process, either different realm (ShadowRealm) or even same realm (Compartment in hardened Realm). Salesforce uses realms, we use Compartments in production, and Moddable uses compartments too in their devices. Let's not claim there is no way to securely run 3rd party JS in the same process
ShadowRealm and Compartment are sandboxes. I'm stating that any combination of the three are ways to safely eval.
08:20
<Mathieu Hofman>
Ah yes, I thought you asked for all 3 ;)
08:20
<rkirsling>
https://github.com/tc39/Reflector/issues/539
awesome, though it seems that I can't access it in its current state (maybe that's okay if it's still undergoing org transfer?)
08:21
<shu>
are you getting an error?
08:21
<shu>
ljharb: ^
08:21
<ljharb>
it should work fine. i'll check to make sure you're invited to the tc39-transfer org … invite sent.
08:21
<Mathieu Hofman>
It's a common reaction we hear from the browser implementors, but lots of production systems run untrusted JS code same process in some fashion, with some kind of sandbox of course
08:22
<rbuckton>
Ah yes, I thought you asked for all 3 ;)
out of process and on a separate machine are mutually exclusive
08:23
<ljharb>
if it's on a separate machine it's definitely also out of process :-p
08:23
<rbuckton>
or maybe I should have clarified OOP (same machine)
08:23
<Marja Hölttä>
Mathieu Hofman: what's the one-sentence summary wrt how they get around Spectre & co when running in the same process?
08:24
<Mathieu Hofman>
deny or virtualize any API that allow measuring time
08:25
<Mathieu Hofman>
also that's if you're concerned about confidentiality. integrity doesn't need denying time tools
08:25
<ljharb>
does that include all i/o? because presumably you could approximate time measurements that way, but maybe it wouldn't be granular enough to matter
08:26
<Mathieu Hofman>
Yes and no. For example Cloudflare Workers pretend time only advances when making external requests. The time is updated to the time the request is processed.
08:28
<Mathieu Hofman>
From what I understand they have some smart logic when you make a request from one worker to another to avoid colluding workers measuring time
08:28
<justingrant>
I had the same question/concern: other than purely "sugar" features like pipeline, most interesting new JS features seem like they'd need some help from the lower-level runtime to have adequate performance and functionality. It'd be good to have some case studies of a few proposals to see what a JSSugar implementation would actually look like in practice.
08:29
<ljharb>
fancy
17:22
<bakkot>
proposal to move the https://github.com/tc39/proposal-type-annotations to https://github.com/tc39/proposal-types-as-comments? people are continually confused about it
17:34
<Rob Palmer>
Can we create a redirect? TaC is the old name.
18:50
<Rob Palmer>
Separate: Please could someone unmute @marjakh:matrix.org:
18:54
<Eli Grey>
wasn't able to participate yet but I'll be available remotely for days 2 & 3 -- could someone help forward remote attendance info?
19:03
<keith_miller>
It's in the reflector for the meeting https://github.com/tc39/Reflector/issues/537 there's a sign-in form that gives you the link
20:15
<Eli Grey>
thanks, I see it now
22:29
<Chris de Almeida>
Separate: Please could someone unmute @marjakh:matrix.org:
that was addreesed yesterday