01:28
<rkirsling>
hmm, I will likely be absent during the R&T timeblock; here's hoping discussion about toString doesn't get too heated
01:33
<rkirsling>
(or maybe we're beyond that now?)
01:41
<rkirsling>
also, anytime folks are looking for a JSC logo for slides: we do have a mascot called Squirrelfish 😆 https://webkit.org/wp-content/themes/webkit/images/squirrelfish-lives.svg
08:36
<Rob Palmer>
good morning, all
08:37
<Rob Palmer>
Thanks to Luca we've made some minor schedule adjustments to better accommodate folks' time constraints
08:44
<Rob Palmer>
This means we have Record & Tuple in the first morning session today, and have pushed out Intl.DurationFormat & LibJS to tomorrow. This makes way for Guy's topics (Import Reflection, Defer Eval) at the end of today.
08:47
<Alex Vincent>
Rob Palmer: I've come to realize my time constraint no longer holds. I'm still in the overflow section, but if a slot opens up, please ignore my posted constraint.
08:48
<Rob Palmer>
Thanks for the update. We will strive to bring overflow items in, as and when extra time frees up.
08:52
<Rob Palmer>
The Google Meet room is up. Please join us. We will begin in 7 minutes.
08:52
<bakkot>
Rob Palmer and other chairs: for my item (Set methods) I want to have the option of using the full 45 minute time box if it's needed, but I'm hoping that it ends up being uncontroversial, in which case it might be as short as 10 minutes
09:02
<Rob Palmer>
Thanks bakkot I have tagged it as such.
09:04
<Michael Ficarra>
oooohhh I like this history slide a lot
09:04
<Michael Ficarra>
definitely going to steal that for my proposal slides from now on
09:05
<Ashley Claymore>
oooohhh I like this history slide a lot
If you like history slides I've got some good news for you!
09:05
<Michael Ficarra>
if you can fit it all on one slide, I'll be impressed
09:06
<littledan>
It would be surprising if Node and Deno really continue to not support this when Chrome does
09:11
<Rob Palmer>
Hey all, as Michael says, please ensure your attendance is logged in the Notes doc.
09:11
<Rob Palmer>
(I deleted the URL because we link everything from the main Reflector post)
09:11
<Rob Palmer>
(I deleted Michael Ficarra's comment accidentally)
09:14
<Luca Casonato>
It would be surprising if Node and Deno really continue to not support this when Chrome does
Deno does support it - I think the BCD data that MDN uses has not been updated yet. I'll get it updated.
09:15
<Michael Ficarra>
Rob Palmer: that was Saboff, not me
09:15
<ryzokuken>
(I deleted Michael Ficarra's comment accidentally)
^
09:16
<Michael Ficarra>
oohhh I see
09:16
<Michael Ficarra>
too early
09:24
<bakkot>
for the notes, who is speaking other than frank?
09:24
<Ashley Claymore>
MAH
09:27
<ryzokuken>
given how many ongoing API proposals could benefit from R&T, shouldn't we be really prioritizing it?
09:28
<ryzokuken>
like... ideally every single Intl constructor should take a record options bag
09:33
<HE Shi-Jun>
The problem is how long we need to wait for r&t 😂
09:33
<bakkot>
I don't think we should start making APIs return records and tuples even when their result is immutable, as convenient as it is
09:33
<bakkot>
everything else is already objects
09:34
<HE Shi-Jun>
So we add r&t but our APIs do not use it, only userland use it?
09:34
<shu>
i'm not even convinced that the different identity thing is that big a problem
09:34
<shu>
caching is good for this, function is good for this
09:34
<bakkot>

so we add r&t but our APIs do not use it, only userland use it?

yeah basically

10:05
<bakkot>
wait temporal has non-symmetric equality
10:05
<bakkot>
I had not realized that
10:06
<bakkot>
seems... not great?
10:07
<shu>
really?
10:07
<shu>
how can it not be symmetric...?
10:07
<bakkot>
that was the claim made in this presentation
10:07
<bakkot>
not literal === equality but equality methods
10:08
<Kris Kowal>
Or as etymologists would call it, anametric equality.
10:09
<Alex Vincent>
page 16 of the notes for the transcript where this was mentioned
10:13
<yulia>
could we take a short break before getting into the queue Rob Palmer ryzokuken
10:14
<Rob Palmer>
yes, we'll do a 10 min intermission as soon as Ashley finishes the presentation part
10:15
<Michael Ficarra>
"ecosystem challenges" and "subtlety" are way too hand-wavey for me to understand what is meant
10:15
<Michael Ficarra>
like what is the concrete thing that those objections refer to?
10:16
<shu>
i have thoughts but my brain
10:16
<shu>
so slow
10:16
<shu>
does not bode well for tomorrow
10:30
<ryzokuken>
not literal === equality but equality methods
this
10:30
<ryzokuken>
it's the compare methods
10:30
<ryzokuken>
basically, since compare accepts plain objects, any superset temporal instances could work as long as they're the argument
10:31
<ryzokuken>
but if the receiver is the superset, it won't work
10:31
<ryzokuken>
(because it will lack certain properties)
10:31
<ryzokuken>
actually, nvm me, the compare methods are static
10:32
<ryzokuken>
so basically as long as the arguments are of types which are supersets of the type whose compare function is called, it will work
10:35
<littledan>
Note, in Romance languages, discuss means argue against, so I think Patrick meant we don’t argue against the goal of immutability
10:37
<jasew>
nicolo-ribaudo: we struggle to hear yulia on this side of the room
10:41
<rbuckton>
I've long been in favor of the introduction of user-defined value types, and it was one of my goals for structs
10:42
<rbuckton>
IIRC, equality has always been a top-level goal?
10:44
<ryzokuken>
another quick reminder, I've settled on a better workflow to admit people into the call ASAP but please feel free to ping me here if you're waiting to be allowed in since Meet doesn't notify me about people waiting to be admitted.
10:44
<nicolo-ribaudo>
IIRC, equality has always been a top-level goal?
Yes, but different champions have been highlighting different goals more so depending on who you asked to it might not have been the first answer
10:44
<rbuckton>
I've long been in favor of the introduction of user-defined value types, and it was one of my goals for structs
As part of this, I had considered #[] and #{} as essentially being to value types the equivalent of [] and {} to reference types, though with the added property of immutability.
10:45
<rbuckton>
If struct had come before R&T, I would have pushed more for R&T to be designed in terms of structs.
10:47
<bakkot>
fwiw I think there's probably a way to get maps and sets which support multiple keys without going full user-defined equality
10:47
<rbuckton>
What I wanted was struct + value types + operator overloading, with flexibility in struct to support mutability/immutability and shareability/transferability/copiability.
10:47
<bakkot>
there was even a proposal for that
10:47
<Ashley Claymore>
rekey + compositekey
10:48
<bakkot>
and we might want that even in a world with R&T given that sometimes you want to key off of objects
10:48
<shu>
i don't see a realistic path in doing value types with operator overloading
10:48
<bakkot>
though I guess symbols as weakmap keys make that less necessary
10:48
<shu>
(for performance)
10:50
<rbuckton>
I've been considering proposing customizable equality/hashing for Map/Set and built-in support for hash code/identity hash acquisition for several years now.
10:50
<rbuckton>
I'm less interested in multi-key maps, and more interested in creating a Map<URL, ...> or Map<Point, ...>, etc.
10:51
<yulia>
I think when we drop equality, the argument for value types is weaker
10:51
<Alex Vincent>
I am very interested in multi-key maps...
10:51
<nicolo-ribaudo>
I think when we drop equality, the argument for value types is weaker
Aren't they just not value types if we drop equality?
10:52
<yulia>
there is also the realms behavior that benefits, but that can be solved in a way similar to shared structs
10:52
<HE Shi-Jun>
I don't understand op overloading argument, I remember op overloading proposal do not allow overload === ?
10:52
<rbuckton>
I am very interested in multi-key maps...
I'm not saying I have no interest, but overriding equality/hash for Map/Set is a much higher priority to me.
10:52
<pipobscure>
Without === there is little value add; as in just use immutable.js and be done with it.
10:52
<yulia>
Operator overloading here is not user defined
10:53
<littledan>
I think when we drop equality, the argument for value types is weaker
It wouldn’t be value types without equality, if by value types we are referencing TC39’s historical investigations
10:53
<Andreu Botella>
That's not really operator overloading then, right? It's just (in theory, regardless of implementation) value types with a === that makes sense for the type
10:54
<HE Shi-Jun>
Operator overloading here is not user defined
but === already be overloaded by different primitive types and objects?
10:55
<littledan>
Without === there is little value add; as in just use immutable.js and be done with it.
I disagree. It would be valuable, just less so.
10:55
<nicolo-ribaudo>
but === already be overloaded by different primitive types and objects?
I guess it depends on how you see R&T. If you say "R&T are like objects", then giving them a different equality feels different from how other primitives have their own equality
10:57
<bakkot>
i still think we should explore making Array.prototype and Object.prototype reject numeric properties
10:57
<HE Shi-Jun>
I guess it depends on how you see R&T. If you say "R&T are like objects", then giving them a different equality feels different from how other primitives have their own equality
Are we talking about user problems or impl complexcity?
10:57
<nicolo-ribaudo>
Implementation complexity
10:58
<HE Shi-Jun>
so I don't fully understand that, i just feel R&T is just another primitive and their equal operation.
10:59
<nicolo-ribaudo>
shu: What does AI mean? I assume you are not proposing we should let artificial intelligence design the proposal
11:00
<shu>
sorry, "Action Item"
11:00
<HE Shi-Jun>
Anyway, we have many use cases of deep equality, so without that we just throw the heavy tasks to developers.
11:07
<ryzokuken>
I wonder if we'd benefit from some design principles, perhaps as invariants.
11:07
<ryzokuken>
Something like https://www.w3.org/TR/html-design-principles/#priority-of-constituencies
11:07
<ryzokuken>
it's unclear what the priority is here
11:08
<Alex Vincent>
rbuckton: ok - I wasn't offering a critique, just a statement of my interest in multi-key maps. 😄
11:08
<HE Shi-Jun>
The real problem is who can represent developers.
11:08
<ryzokuken>
that's a problem indeed
11:08
<Rob Palmer>
we resume at the top of the hour 1pm local time, which is in 52mins
11:08
<ryzokuken>
but even in the presence of a representative, do we care?
11:09
<rbuckton>
littledan: I've been thinking about the "dynamic comparison in Map/Set" thing for awhile, and started working on a draft of a proposal awhile ago.
11:09
<nicolo-ribaudo>
The real problem is who can represent developers.
We have many delegates that are JavaScript developers and not just standard/engine engineers
11:09
<rbuckton>
littledan: I've been thinking about the "dynamic comparison in Map/Set" thing for awhile, and started working on a draft of a proposal awhile ago.
https://gist.github.com/rbuckton/f8c2ac278b796324a06410e59c56eb10 (4 years old at this point)
11:10
<HE Shi-Jun>
We have many delegates that are JavaScript developers and not just standard/engine engineers
yeah, but who can say " I represent the majority of developers"?
11:10
<waldemar>
I don't quite understand what alternative Yulia has in mind, and I'd like to know what it is.
11:12
<rbuckton>
Plus something like Equaler would have value in other APIs like .includes and .groupByToMap
11:27
<littledan>
I don't quite understand what alternative Yulia has in mind, and I'd like to know what it is.
Me too
11:27
<littledan>
https://gist.github.com/rbuckton/f8c2ac278b796324a06410e59c56eb10 (4 years old at this point)
Thanks for sharing this!
11:29
<rbuckton>
Thanks for sharing this!
I also have https://esfx.js.org/esfx/api/equatable.html?tabs=ts as an example implementation that I'm heavily using in a few projects, along with https://esfx.js.org/esfx/api/collections-hashmap.html?tabs=ts
11:55
<yulia>
I was cryptic in my "i don't have much time" -- I'm not dying but ill be taking a break in march. We have some great folks from mozilla taking over though
11:56
<yulia>
I don't quite understand what alternative Yulia has in mind, and I'd like to know what it is.
I don't have 100% a full solution, I would like to see an investigation of building this on top of shared structs or a clear problem statement. so far it is usually a compound description of the constraints that lead us to a primitive, but many of them are issues i see more broadly in the language and i think would be beneficial if expanded
11:58
<littledan>
I don't have 100% a full solution, I would like to see an investigation of building this on top of shared structs or a clear problem statement. so far it is usually a compound description of the constraints that lead us to a primitive, but many of them are issues i see more broadly in the language and i think would be beneficial if expanded
I think the goals have been shared lots of times; I honestly don’t know what kind of answer would work better for you.
11:58
<littledan>
The presentation had a slide shown twice with three high-level goals, and went into detail about how they are related
11:59
<Rob Palmer>
We are restarting plenary in 1 minute.
11:59
<shu>
Ashley Claymore shared with me an sketch of building on top of shared structs, could you also share it with yulia if you didn't already?
12:00
<littledan>
Fwiw here is another gist around an alternative, trying to draw out how there really is a spectrum of options https://gist.github.com/littledan/4b9c797f3e70d3531fcf32decc6e9754
12:00
<littledan>
Fwiw here is another gist around an alternative, trying to draw out how there really is a spectrum of options https://gist.github.com/littledan/4b9c797f3e70d3531fcf32decc6e9754
I believe this matches what something around “shared structs” would be
12:01
<yulia>
I think i outlined a couple of things that might work? and also the conditions that would resolve our concerns. I am not sure what you are asking
12:01
<littledan>
(There aren’t all that many observable properties that you derive from trying to align with shared structs. Seems like typeof, ===, not sure what else)
12:01
<yulia>
its another thing if you don't like the solution, I still consider them valid and the implementer concerns are significant. I wouldn't bring this up otherwise
12:01
<Rob Palmer>
Thanks to Ashley and Linus and Andreu for note taking!
12:02
<littledan>
I think i outlined a couple of things that might work? and also the conditions that would resolve our concerns. I am not sure what you are asking
I mean, it is Ok to disagree with the goals but I think they were stated. This was actually the focus of the presentation.
12:03
<yulia>
right and what I said was that the goals that are being addressed are broader issues within the language. they are not limited to just value types
12:04
<littledan>
its another thing if you don't like the solution, I still consider them valid and the implementer concerns are significant. I wouldn't bring this up otherwise
Implementer feedback is definitely good. I think it is worth thinking about R&T as objects as well. If you have ideas about details of an alternative, it will be great to discuss them offline. I can see lots of options, as I went into in the gist linked above.
12:05
<yulia>
yes, thank you for doing that, and i was sort of referencing it because I know this isn't the ideal version of the proposal as you see it. I just think it should be seriously considered
12:05
<yulia>
for now, id like to focus on the module layer zero proposal and we can come back to this, but i think we are pretty much on the same page in terms of where things are right now
12:05
<littledan>
Maybe next time we discuss R&T we should go over various options in more detail to discuss pros and cons
12:06
<yulia>
In part the goal today was to also bring the concerns we have already discussed among champions and implementers to the broader committee, so we are sort of going over ground a second time -- what I am saying now is not substantially different from our prior meetings
12:06
<yulia>
just to clarify, in case it seemed like i was asking for something new
12:07
<littledan>
In part the goal today was to also bring the concerns we have already discussed among champions and implementers to the broader committee, so we are sort of going over ground a second time -- what I am saying now is not substantially different from our prior meetings
Yes, I really appreciate that you shared that with everyone
12:19
<yulia>
what does "kicker" mean here?
12:21
<Mathieu Hofman>
though I guess symbols as weakmap keys make that less necessary
Not really, being able to create a composite key from multiple unique symbols is still extremely valuable. But it does go into the ephemeron complexities that Shu mentioned earlier
12:22
<nicolo-ribaudo>
what does "kicker" mean here?
Something that starts the loading/linking/evaluating process
12:23
<yulia>
thanks
12:23
<Mathieu Hofman>
I'm not saying I have no interest, but overriding equality/hash for Map/Set is a much higher priority to me.
To clarify, how is this different than a rekey/identity configuration for the Map/Set? I don't think there is a safe way to make the equality semantics controlled by the target key, unless the key is born immutable.
12:25
<eemeli>

As discussed earlier today re Intl.Locale, I wonder if this is true?

const src = ...
new Module(src).source === new Module(src).source // ???
12:26
<Michael Ficarra>
module source is no more of a new form of eval than importing a data URI which you can do today
12:26
<nicolo-ribaudo>

As discussed earlier today re Intl.Locale, I wonder if this is true?

const src = ...
new Module(src).source === new Module(src).source // ???
I would expect yes, it should be new Module(src).source === src
12:28
<ljharb>
Kris Kowal: re the queue, can you help me understand the use cases for having ModuleSource instead of just passing a string to Module?
12:28
<Luca Casonato>
shu: Yes, the import hook is shallow
12:28
<rbuckton>
Equality semantics aren't necessarily controlled by the target key, but by the provided Equaler. The gist from 4 years ago is a little weaker in that regard, and so is the @esfx/equatable implementation I mentioned earlier. "rekey" assumes you can convert the key into something with an equivalent identity but that can significantly increase the complexity of user code (i.e., needing to introduce a WeakMap/FinalizationRegistry and roll your own identity generation). Equality and hashing is often easier and generally only involves math and a built-in mechanism to acquire an identity hash for objects.
12:28
<shu>
Luca Casonato: okay, just to make sure i understand
12:29
<rbuckton>
The Equaler approach also mirrors what many implementations are already doing internally.
12:29
<shu>
Luca Casonato: to have it be deep, the importhook itself needs to return Module instances that are themselves passed the import hook
12:29
<Luca Casonato>
yes
12:30
<Michael Ficarra>
bakkot: it's not a new kind of eval, import is the evaluator here
12:31
<bakkot>
it's a new kind of eval, you can't use dynamic eval to evaluate an arbitrary string
12:31
<nicolo-ribaudo>
Can we try giving 1 minute each for the replies to this topic?
12:32
<Michael Ficarra>
bakkot: data URIs
12:32
<Luca Casonato>
and blob urls
12:32
<bakkot>
those aren't in 262 and have different CSP rules than eval does
12:33
<rbuckton>
it's a new kind of eval, you can't use dynamic eval to evaluate an arbitrary string
"dynamic eval" or "dynamic import"?
12:33
<bakkot>
and also just because it's possible to use something obscure to accomplish a thing does not mean that we should be providing a first class way of doing it
12:36
<ljharb>
imo Module is the same as Function and friends
12:36
<Luca Casonato>
bakkot: Are you opposed to dynamic instantiation of module instances in general, or only from arbitrary text?
12:36
<ljharb>
it's a constructor to create invokeable code you can pass around. so far, all of those take a string of source
12:36
<bakkot>
Luca Casonato: I don't know what "dynamic instantiation" means if not "from arbitrary text"
12:36
<bakkot>
but it's the "arbitrary text" I have a problem with, yes
12:36
<ljharb>
nobody objected to AsyncFunction etc taking a string, why would Module not?
12:37
<bakkot>
Function already existed, AsyncFunction is not that different from it
12:37
<Luca Casonato>
import reflection: import module foo from "./foo.js"; await import(foo)
12:37
<bakkot>
Module is quite different
12:37
<bakkot>
Luca Casonato: totally fine with that
12:37
<ljharb>
as dan said on the queue, i can eval(`module { ${source} }`) anyways, how is that different from passing source in directly?
12:38
<bakkot>
everyone knows eval is evil
12:38
<bakkot>
"I can already do this by using eval" is not a reason to add a feature
12:38
<littledan>
as dan said on the queue, i can eval(`module { ${source} }`) anyways, how is that different from passing source in directly?
As Kris said, this is about making eval deniable
12:38
<littledan>
Not just through CSP but by deleting the property
12:38
<ljharb>
oh sure in this case i meant "via ModuleSource"
12:39
<ljharb>
(i don't think it's clear that deniability is a sufficient motivation to create an entire class, but that's a separate discussion)
12:39
<littledan>
I share bakkot’s concern generically and was persuaded by the eval injection risk
12:40
<Luca Casonato>

bakkot: are you ok with:

import module foo from "./foo.js";
const newMod = new Module(foo.source);
await import(newMod);
12:40
<rbuckton>
Though you will now also need to deny ModuleSource, since await import(new Module(new ModuleSource(code))) is just indirect eval.
12:40
<bakkot>
Luca Casonato: assuming foo.source is opaque, yes, I think so
12:41
<Luca Casonato>
Luca Casonato: assuming foo.source is opaque, yes, I think so
Yes, foo.source is a ModuleSource instance. There is no access to the module source text.
12:42
<bakkot>
though, I should say, I also don't understand the need for that
12:42
<littledan>
though, I should say, I also don't understand the need for that
This lets you relink dependencies (eg for testing) which is interesting
12:43
<bakkot>
yeah, the testing case is interesting, but not compelling to me on its own
12:43
<bakkot>
I am very reluctant to add features which are only motivated by testing
12:44
<ljharb>
what about feature-detection? like "is TLA supported"
12:44
<yulia>
im sort of swayed by hot reloading as a use case, in particular having no-reload updates
12:44
<rbuckton>
I find the testing case compelling, but there are potential issues there as well. If you can't remove modules from the module cache, re-importing the same module with different dependencies in a test runner will just continuously grow the module cache until you OOM.
12:44
<yulia>
so, similar to erlang behavior for swapping out running code is something i sometimes wistfully think about.
12:44
<Luca Casonato>
what about feature-detection? like "is TLA supported"
new ModuleSource would synchronously throw on syntax errors
12:44
<eemeli>
I get the sense that this first proposal is including ModuleSource in order to use it esp. for the introspection stuff that's coming in a later proposal. Could we not have a first proposal that has the source as a string and leaves out module.source, and then a follow-on proposal that modifies this proposal before it reaches stage-4 with the ModuleSource features that are in it now?
12:44
<Mathieu Hofman>
Right but engines can guarantee the stability of this, where delegating to the program, I don't see how it can
12:45
<ljharb>
right, but how could i detect it if i can't make a module from a string
12:45
<rbuckton>
Right but engines can guarantee the stability of this, where delegating to the program, I don't see how it can
How important is that stability when you are opting into the behavior by providing a custom equaler?
12:45
<Luca Casonato>
right, but how could i detect it if i can't make a module from a string
yeah, exactly
12:45
<yulia>
cc bakkot in case this is possibly interesting
12:45
<bakkot>
what about feature-detection? like "is TLA supported"
I don't see offhand why that would be important enough but am open to being convinced
12:46
<shu>
Kris Kowal: thanks the developer - production split is a helpful framing
12:46
<ljharb>
eg i want to know if it's worth trying to import a module that i know requires TLA support, and i support envs that lack it, and i don't want to even bother making the network request if it lacks it
12:46
<nicolo-ribaudo>

I had in on the queue but didn't get to it, but ModuleSource is to JavaScript what WebAssembly.Module is to WASM.

A new Module could also take, for example, a WebAssembly.Module

12:47
<shu>
let me think on that, but sounds like a starting point to how to think about getting ahead of performance footguns and how to message it
12:47
<nicolo-ribaudo>
Because WebAssembly.Module is the representation of the wasm source, and it is stateless
12:47
<bakkot>
ljharb well, nothing is going to have ModuleSource but not TLA, so presumably you're imagining some other syntax?
12:48
<rbuckton>
eg i want to know if it's worth trying to import a module that i know requires TLA support, and i support envs that lack it, and i don't want to even bother making the network request if it lacks it
Would you not generally know this up front, given that its usually unsafe to eval code you don't control anyways?
12:48
<Luca Casonato>

It is the compiled module source, that you can also use to get the list of imported specifiers, and list of exported binding identifiers. ModuleSource could provide the same for JS modules. Ie ModuleSource#imports and ModuleSource#exports

See also https://github.com/tc39/proposal-compartments/blob/master/1-static-analysis.md

12:49
<ljharb>
Would you not generally know this up front, given that its usually unsafe to eval code you don't control anyways?
i'd know that the code i'm importing has TLA, of course - but i don't know what the env supports
12:49
<ljharb>
ljharb well, nothing is going to have ModuleSource but not TLA, so presumably you're imagining some other syntax?
ha, true, so yes, swap TLA for "any future module-only syntax we add"
12:50
<ljharb>
(altho ModuleSource can probably be polyfilled since every engine has a way to create ESM from a string, despite it not being in 262)
12:50
<Luca Casonato>
(altho ModuleSource can probably be polyfilled since every engine has a way to create ESM from a string, despite it not being in 262)
do browsers have a synchronous way to do this? I thought not
12:51
<ljharb>
oh true, no, only async
12:51
<nicolo-ribaudo>
do browsers have a synchronous way to do this? I thought not
You replace the ModuleSource global with ModuleSource+Babel, generating an object that toStrings to a data url?
12:51
<rbuckton>
i'd know that the code i'm importing has TLA, of course - but i don't know what the env supports
This still seems more like an infrastructure issue. If you know what the code you're going to send needs, you can feature test the env early, before you send any code across the wire.
12:51
<ljharb>
rbuckton: exactly. how can i feature-test the env without the ability to make a module from a string?
12:52
<rbuckton>
package.json: { "engines": { "node": "^19" } }?
12:52
<ljharb>
that covers node, but not browsers or node-like things
12:52
<nicolo-ribaudo>
That's very specific to a single env
12:52
<nicolo-ribaudo>
Not even to an env, but to package managers
12:52
<ljharb>
and there could also be a fallback, so i wouldn't need to artificially restrict compat
12:53
<linusg>
bakkot: "D denting" -> "dedenting" replacement would be nice
12:53
<bakkot>
done
12:54
<rbuckton>
True, but you're not just sending code to a random environment. I assume there's some setup/handshake between you and the remote. That's when I'd perform feature testing or inform the client what the remote supports.
12:55
<rbuckton>
And even if there isn't, if you have ensured the minimum level of support for sending a module over the wire, you can send one that performs the necessary feature tests in advance (i.e., send a module { some new syntax } over the wire during handshake and see if that fails)
12:55
<Mathieu Hofman>
I assumed implementations would care as it would allow user code to execute in the middle of internal Map/Set implementations. This is also a problem for the Map user if the equality somehow further delegates to the objects themselves.
12:58
<rbuckton>
I assumed implementations would care as it would allow user code to execute in the middle of internal Map/Set implementations. This is also a problem for the Map user if the equality somehow further delegates to the objects themselves.
This came up in a discussion over the complexity of introducing a value type with unique === semantics. The question would be whether implementers would find the necessary changes to handle runtime comparisons would be a less complex alternative.
12:59
<rbuckton>
I agree it would add complexity, and the justification for that added complexity would be to avoid worse complexity elsewhere.
12:59
<ljharb>
yes i agree, but i'm saying that you can not perform that feature testing in the first place without this capability
12:59
<ljharb>
at any time
13:00
<Kris Kowal>
(@bakkot Regarding new paths to eval, to restate @littledan from the queue, eval('module {}') is equivalent but worse, because injection.)
13:00
<bakkot>
Kris Kowal right but people know not to use eval
13:00
<bakkot>
we shouldn't be encouraging them to do equivalent things
13:02
<rbuckton>
yes i agree, but i'm saying that you can not perform that feature testing in the first place without this capability
If you have module {}, then you can. You don't need ModuleSource(text) or source-text access to define those feature tests. To be clear, I'm not opposed to ModuleSource(text), I just don't find this to be a compelling example.
13:04
<rbuckton>

In fact, in a discussion with my team it was asked why JS should even have module {} if it could just have

javascript` /*module body*/ `

Though I fully see the CSP concerns as being a major reason for a syntactic alternative.

13:08
<Kris Kowal>
we shouldn't be encouraging them to do equivalent things
My point is not that we should encourage such things, but that we cannot prevent them by eliding ModuleSource from the language. We can prevent ModuleSource from being useful in places where it shouldn’t be useful using CSP, but having ModuleSource is necessary to parse-and-not-execute safely and accurately.
13:14
<ljharb>
hm, could you do isSubsetOf with a WeakSet that has a size own data property set to Infinity?
13:26
<Mathieu Hofman>
Regarding the feature detection, I fail to see how this is a problem specific to the modules proposals, or that the module proposals should solve. This is a broader ecosystem issue. Every new syntax we add has the same problem, and it's impossible to for a publisher to feature test what syntax the target environment might support. This is the case for servers sending modules to web clients, but also for library authors not knowing anything about the environment of the consumers. IMO, this is not something the language can solve, but that needs some kind of holistic approach. One thing I've been pondering is whether authors could somehow document which syntax features their code is using, and have better ways to know which syntax is supported by target environments, so that tooling (servers, transpilers, etc.) could do impedance matching.
13:28
<Rob Palmer>
We resume 14:40 (11mins time)
13:28
<rbuckton>
Hopefully back in 10 min, dogs need a walk.
13:28
<Ashley Claymore>
🎉 So excited this got stage 3. Lovely proposal
13:30
<ljharb>
the difference is that modules, like functions, are first-class values that have stored code that can be executed
13:31
<Justin Ridgewell>
Rob Palmer: If possible, I'd love to come back to String.dedent later in the meeting.
13:34
<Michael Ficarra>
Justin Ridgewell: any reason why the caching issue can't be worked out on the issue tracker or in an incubator call? does it still need the whole committee's attention?
13:35
<Justin Ridgewell>
Because I'd like to get Stage 3
13:35
<Michael Ficarra>
oh, has the naming issue been worked out already?
13:36
<Justin Ridgewell>
If we can agree on the caching behavior in issue tracker, I'd like to finalize it and ask for advancement.
13:36
<Justin Ridgewell>
Naming issue?
13:36
<bakkot>

hm, could you do isSubsetOf with a WeakSet that has a size own data property set to Infinity?

yes, and more generally you can make fake wrappers which will let you pretend to be a set for a lot of cases. like, to union with array: let fakeSet = arr => ({ size: arr.length, keys: () => arr.values(), has: () => { throw 'not reached' } }); let result = foo.union(fakeSet([0, 1, 2]))

13:38
<Michael Ficarra>
Justin Ridgewell: oops, I was mixing dedent and groupBy together, sorry
13:38
<Michael Ficarra>
wow it's amazing how dumb I am when tired
13:39
<Michael Ficarra>
can't wait to give the iterator helpers presentation on day 3 right after waking up :-)
13:39
<Justin Ridgewell>
Lol, my ability to explain talk during the presentation isn't great either. Too sleepy
13:40
<shu>
i'm no longer sleepy
13:40
<shu>
i'm at the my head feels detached state
13:41
<Kris Kowal>
same + toddler woke up, ready for another energy-filled day
13:44
<Michael Ficarra>
that was fast :-)
13:54
<shu>
not as fast as the inner loop of an optimized IsWellFormed optimization
13:54
<Michael Ficarra>
shu: you better hope so
13:55
<Michael Ficarra>
I want constant time, make it happen
13:55
<rbuckton>
I'm finding the fact module importing a ModuleSource and not a Module slightly confusing from the perspective that the keyword isn't quite aligned to the type.
13:56
<apaprocki>
I want constant time, make it happen
see TDZ... #define JSCHAR_IS_JUST_CHAR IsWellFormed=>return true;
13:56
<Michael Ficarra>
apaprocki: not a joke, we should be able to make it constant time (amortized)
13:56
<Robert Pamely>
I'm finding the fact module importing a ModuleSource and not a Module slightly confusing from the perspective that the keyword isn't quite aligned to the type.
Perhaps it's confusing because it is still using the import keyword
13:56
<Christian Ulbrich>
FWIW, TS also used a similar syntax for type imports :import type {...}
13:56
<ljharb>
I'm finding the fact module importing a ModuleSource and not a Module slightly confusing from the perspective that the keyword isn't quite aligned to the type.
that's the same complaint i have about reflect: 'module'
13:57
<Kris Kowal>
I'm finding the fact module importing a ModuleSource and not a Module slightly confusing from the perspective that the keyword isn't quite aligned to the type.
I am encouraging a return to the consideration of import moduleSource from './example' with { reflect: true } to mirror the proposed dynamic import. This is consistent with a need to confine dynamic import and washes back from that.
13:57
<Mathieu Hofman>
exactly, this is already a problem for Function and eval, so why would Module be subject to different requirements
13:58
<ljharb>
that seems like it would allow with to be expanded in unforseeable ways in the future, which sounds like a downside to me
13:58
<ljharb>
i agree it should have the same requirements as Function - which includes that it takes a string of source code
13:58
<rbuckton>
I am encouraging a return to the consideration of import moduleSource from './example' with { reflect: true } to mirror the proposed dynamic import. This is consistent with a need to confine dynamic import and washes back from that.
It's more that it seems like renaming ModuleSource->Module and Module->somethingelse would be clearer. Especially since the ModuleSource equivalent in WASM is WebAssembly.Module.
13:58
<Kris Kowal>
I’d previously encouraged import module to mirror import.module for static vs dynamic variants, but I have retracted that.
13:59
<Kris Kowal>
I’d be excited to entertain ideas for somethingelse.
13:59
<Kris Kowal>
I have none.
13:59
<Mathieu Hofman>
I thought we had settled that a level of indirection through ModuleSource was not a meaningful difference.
13:59
<bakkot>
it is surprising to me that import module does not actually evaluate the module, so I am also supportive of import moduleSource or something
13:59
<Kris Kowal>
Though, it’s a constrained problem… module {} instanceof Module makes much sense.
13:59
<bakkot>
like I think of the regular import statement as importing a module
14:00
<yulia>
my preference would be something like with
14:00
<bakkot>
so "import module" is confusing
14:00
<Kris Kowal>
I agree.
14:00
<Kris Kowal>
And suggest that import moduleSource from 'example' with { reflect: true } should address that concern.
14:01
<Kris Kowal>
like I think of the regular import statement as importing a module
That’s very reasonable, though it doesn’t provide any reflection of that module.
14:01
<Christian Ulbrich>
I tend to also agree, because there is a certain overlap in naming; import is about importing modules...
14:01
<yulia>
I feel like that also works well with dynamic import
14:01
<bakkot>
That’s very reasonable, though it doesn’t provide any reflection of that module.
well, the import * as form does, arguably
14:01
<bakkot>
but yes
14:02
<Kris Kowal>
Right, I agree and also suggest const moduleSource = await import('example', { reflect: true}) to pair.
14:02
<ljharb>
i really don't like the "with" object, or any object form. are there long term, concrete, viable plans to add something else to the object?
14:02
<Kris Kowal>
Note (module {}).source instanceof ModuleSource intentionally reads correctly.
14:03
<Kris Kowal>
i really don't like the "with" object, or any object form. are there long term, concrete, viable plans to add something else to the object?
with { phase: 'linked' } would be a reasonable extension.
14:03
<yulia>
with { lazy: true } would also be a path
14:03
<yulia>
rather than adding arbitrary new syntax
14:04
<ljharb>
i'd love to understand more about how those proposals would work
14:04
<Kris Kowal>
with also pairs well with dynamic import options bag, as opposed to variadic args.
14:04
<ljharb>
sure, but dynamic import can accept a similar-but-different form in its options bag
14:04
<Kris Kowal>
Yulia will be talking about lazy in this meeting.
14:04
<ljharb>
import module and { module: true } is perfectly sensible
14:05
<ljharb>
if i'm awake for that, that's great, but timezones make that hard
14:08
<Michael Ficarra>
okay I think I finally understand why this doesn't solve deferred evaluation: the deferred eval use case still wants to load the whole module graph eagerly, right? just not start evaluating?
14:08
<Kris Kowal>
This is a strawman: As for phase: 'linked', the goal state of import is implicitly is executed whereas with import module (by whatever syntax) has a goal state of shallowly loaded. phase would provide an avenue for targetting an intermediate phase, like linked, which would ensure the transitive dependencies have loaded (or loading this module will fail). This is useful for communicating to bundlers and runtimes different performance profiles for application startup, like code splitting.
14:08
<Kris Kowal>
okay I think I finally understand why this doesn't solve deferred evaluation: the deferred eval use case still wants to load the whole module graph eagerly, right? just not start evaluating?
Correct.
14:08
<yulia>
okay I think I finally understand why this doesn't solve deferred evaluation: the deferred eval use case still wants to load the whole module graph eagerly, right? just not start evaluating?
yes thats right
14:09
<Michael Ficarra>
thanks 🙂
14:12
<nicolo-ribaudo>
Maybe ModuleInstance&ModuleSource, and the syntax could be import instance or import source
14:12
<Christian Ulbrich>
yulia: Exactly. I also see this confusion.
14:12
<yulia>
import source may work if we go in that direction, and it may be the closest to what is happening now
14:12
<yulia>
instance is also an overloaded term as developers may think that this gets around module singleton-ness
14:12
<Robert Pamely>
isn't import instance just import?
14:13
<yulia>
^ also that confusion is likely
14:13
<nicolo-ribaudo>
import instance would give you a ModuleInstance object
14:13
<eemeli>
I think I like import source.
14:15
<ljharb>
import is like "import instance and extract bindings", maybe?
14:16
<yulia>
import is import and execute a module -- instance, in this case, means something different and can still be executed
14:16
<yulia>
thats why you can await import it
14:16
<yulia>
its more like module record maybe is what i shoud say?
14:17
<nicolo-ribaudo>
Yes an instance is exactly a module record, just exposed to JS as an object
14:17
<Rob Palmer>
Has this topic been discussed with bundlers on the TC39 Tools call?
14:17
<eemeli>
I don't see why we'd need more than two statements here; something like import + import source would also allow for an instance to be constructed from the latter.
14:19
<shu>
nicolo-ribaudo: wait, doesn't omitting the handler get you what's equivalent to the host?
14:20
<Kris Kowal>
nicolo-ribaudo: wait, doesn't omitting the handler get you what's equivalent to the host?
Yes.
14:20
<Kris Kowal>
In this sense, import reflection simply defers the phases past load.
14:20
<nicolo-ribaudo>
Yes but Module instances don't have the [[HostDefined]] slot provided by the host
14:20
<shu>
which Module instances?
14:21
<nicolo-ribaudo>
Created by new Module
14:21
<shu>
gotcha, but import module returning module instances can have [[HostDefined]]
14:21
<Luca Casonato>
import reflect foo from "./foo.js"; foo instanceof Module; // true
14:21
<nicolo-ribaudo>
ModuleSource lacks the referrer URL, which is stored in the [[HostDefined]] slot of Module Records
14:21
<ljharb>
chairs, the queue isn't advanced properly
14:21
<nicolo-ribaudo>
[[HostDefined]] belongs to Module and not ModuleSource, because it contains data specific to that instantiation
14:22
<nicolo-ribaudo>
So if import *keyword* returns a Module object, it has all the data necessary to resolve the dependencies when later imported. If it returns a ModuleSource, new Module(thatThing) doesn't have the necessary data
14:23
<shu>
Kris Kowal: why isn't it the case that a new Module that have the host default handler get the [[HostDefined]] slot?
14:23
<nicolo-ribaudo>
i.e. the base URL, + maybe what HTML calls "fetch options"
14:23
<nicolo-ribaudo>
Kris Kowal: why isn't it the case that a new Module that have the host default handler get the [[HostDefined]] slot?
Even if we had that, the host wouldn't know which base URL to put in that slot
14:23
<ljharb>
so is the queue now for the previous topic?
14:23
<Kris Kowal>
Nicolò of course is the authority on the proposed spec text, but the intent is that the Module carries host-defined import behavior and ModuleSource carries host-defined origin information and those are separate concerns. The latter would prevent import in a no-unsafe-eval for a ModuleSource constructed from text. The former defines link behavior.
14:23
<shu>
oh sorry, i thought you wrote that spec
14:23
<shu>
hm i see
14:24
<shu>
okay that seems like a good argument for returning Module instance
14:24
<nicolo-ribaudo>
Caridy wrote it, I then PRed to rebase it on top of the refactor changing much of the loading logic
14:24
<shu>
but i think my brainpower has degraded from small child to golden retriever
14:24
<shu>
is this the last item
14:24
<ryzokuken>
we might bring something forward
14:25
<Rob Palmer>
something delicious and entertaining
14:26
<Alex Vincent>
I admit to being ready with my presentation if called upon.
14:27
<nicolo-ribaudo>
is this the last item
Probably we'll also have "An introduction to the LibJS JavaScript engine"
14:31
<littledan>
Nicolò of course is the authority on the proposed spec text, but the intent is that the Module carries host-defined import behavior and ModuleSource carries host-defined origin information and those are separate concerns. The latter would prevent import in a no-unsafe-eval for a ModuleSource constructed from text. The former defines link behavior.
Right, I didn’t explain this clearly but to be able to use ModuleSource we would need it to be accompanied by all sorts of other meta information
14:31
<littledan>
I think this is what Guy was imagining, and that it would live in WebAssembly.Module
14:32
<littledan>
(We may still want to propagate some of that information there)
14:32
<nicolo-ribaudo>
I with we had "TC39 meeting: modules edition" :P
14:33
<Kris Kowal>
Like Shark Week
14:44
<rkirsling>
live every week like modules week
14:48
<ryzokuken>
if we have a few more days this intense, I'll need a glucose drip
14:48
<bakkot>
are any of the other engines using bleeding-edge C++?
14:48
<bakkot>
I haven't been paying attention to the C++ world much in the last... uh, decade or so, I guess
14:49
<yulia>
i think we technically have c++20?
14:49
<yulia>
whether we use it fully or not is another question
14:49
<apaprocki>
mfbt has a lot of newish stuff used by sm
14:54
<rkirsling>
I'm not certain if "full C++20" is a reasonable state at the moment? but I think WK is "17 with a small selection of 20 things"
14:56
<shu>
i don't even know how to read bleeding edge C++
14:56
<apaprocki>
there's so many useful things in 20
14:57
<apaprocki>
we add lots of the useful library bits in our stl so we get them even in +03
14:57
<shu>
"signed integers are 2's complement"
14:57
<shu>
for real
14:57
<apaprocki>
ostringstream::view() ftw
15:11
<shu>
wait what's the timebox for this
15:11
<shu>
does today go past 7?
15:12
<Rob Palmer>
the meeting ended 12 mins ago - apologies for the overrun
15:12
<ljharb>
snek: can you add libjs to esvu?
15:13
<snek>
ljharb: didn't I already do that?
15:13
<Christian Ulbrich>
linus said so :)
15:13
<ljharb>
oh hm, maybe i just need to update esvu
15:13
<ljharb>
npx esvu --engines doesn't list it for me
15:13
<snek>
https://github.com/devsnek/esvu/blob/master/src/engines/libjs.js
15:14
<ljharb>
how do i list all the available engines?
15:15
<littledan>
That was a very satisfying closing topic
15:15
<littledan>
So exciting
15:15
<snek>
what was the closing topic?
15:15
<snek>
I missed the whole meeting 😭
15:15
<apaprocki>
libjs
15:15
<snek>
oh nice yeah
15:15
<Ashley Claymore>
100% - LibJS found spec typos in the change-array-by-copy proposal. Very thankful for the issues they raised
15:16
<snek>
now if you had implemented change-array-by-copy in engine262... :P
15:17
<ljharb>
hmm, Error: LibJS does not have binary builds for darwin-x64 - can i not install it on a mac?
15:17
<snek>
I think it's Linux x64 only
15:17
<snek>
they'd need to expand their CI
15:17
<Christian Ulbrich>
Use a x86 shell...
15:18
<ljharb>
oof
15:18
<ljharb>
linusg: any chance of making a binary for mac? :-)
15:20
<linusg>
I think the main problem with that is that the build is done when test262 runs, which we have a dedicated (Ubuntu) CI runner for - maybe it can cross compile for macOS though, I'll ask around :)
15:25
<snek>
GitHub actions has mac instances
19:24
<Ashley Claymore>
now if you had implemented change-array-by-copy in engine262... :P
I did start to look into this, they beat me to it 😆