00:47
<snek>
is tcq still dead?
00:47
<snek>
i guess the website is still intermittent
00:49
<snek>
ah i see a link was posted mere moments ago
01:00
<bakkot>
meeting is starting, for anyone else who is remote and not paying enough attention to the clock
01:02
<ptomato>
I must be blind, but I can't find the google form to get the video chat link?
01:02
<ryzokuken>
https://github.com/tc39/Reflector/issues/564
01:03
<nicolo-ribaudo>
You are the second person asking, we should make it more visible in the issue
01:03
<bakkot>
it is under the "Video Conference" heading
01:03
<bakkot>
in said thread
01:04
<rkirsling>
woot woot another japan meeting begins
01:04
<Michael Ficarra>
break at 10:00?
01:06
<rkirsling>
who doesn't love starting with a break
01:22
<Chris de Almeida>
sorry about that, I will fix
01:23
<Chris de Almeida>
TCQ is buggy af.. I am struggling
01:23
<Chris de Almeida>
  1. move agenda topic
  2. wait
  3. reload page
  4. hope the item is where it's supposed to be
  5. GOTO 1
01:29
<Michael Ficarra>
lol [[IsLockFree1]] would be a little silly
01:29
<Justin Ridgewell>
What was the change in the copyright?
01:29
<Justin Ridgewell>
Comparing 262’s and 426’s copyright text, it looks the same.
01:30
<Michael Ficarra>
the copyright notice was just some random copyright text that we have no idea where it came from
01:30
<ryzokuken>
we hadn't used the alternate copyright for either standard
01:30
<Michael Ficarra>
@justingrant are you comparing the yearly releases or the editors' drafts?
01:30
<Michael Ficarra>
we've already updated the editors' drafts
01:30
<nicolo-ribaudo>
Shhhh we are dealing with it, Aki noticed one second after saying yes
01:30
<jkup>
426 is also incorrect
01:31
<Justin Ridgewell>
Comparing the published specs
01:31
<Justin Ridgewell>
@nicolo-ribaudo just said it was already correct
01:31
<Aki>
https://github.com/tc39/agendas/blob/main/2025/tc39-2025-049-Rev1.pdf
01:31
<Aki>
I was wrong
01:32
<Aki>
it's is wrong
01:33
<Rob Palmer>
You are welcome to prepare another vote. I think we could get through it very quickly.
01:33
<Aki>
that's the wrong link
01:33
<Aki>
https://github.com/tc39/ecma426/pull/237
01:33
<rkirsling>
if my work focus hadn't changed, I would be likely interested in editor group :-/ (but then timezones would also be messy)
01:35
<bakkot>
https://github.com/tc39/ecma262/pull/3701
01:35
<Justin Ridgewell>
Diff:
01:39
<nicolo-ribaudo>
It would be a very uncontroversial vote, but given it's not urgent maybe we should wait until next time? I assume the same things I said about stage advancement materials also apply to votes materials
01:39
<nicolo-ribaudo>
(I would be happy to "vote" yes now though)
01:40
<Aki>
I actually just turned the PR to a draft bc I want Samina's eyes on it before I change anything formal.
01:42
<Ashley Claymore>
[[IsLockFreeToo]]
01:56
<danielrosenwasser>
Is this only an error if there's an ambiguous named import, or if the module in question imports two conflicting bindings?
01:56
<bakkot>
only if you actually request the name
01:56
<rkirsling>
ruh roh engine262
01:56
<danielrosenwasser>
This is actually news to me
01:57
<bakkot>
ambiguous exports like this are actually stripped from namespace exports, which is fun too
01:58
<bakkot>
ljharb: note the export * from in //library
01:58
<bakkot>
it is exporting all bindings from both left and right
01:58
<bakkot>
but both of those export a ns binding
02:00
<Ashley Claymore>
I'm pleased we at least chose to drop clashing export * rather than something more fun like "first one wins"
02:01
<eemeli>
Do I understand right that we have yet another concept of equality defined by multi-path-importability?
02:02
<bakkot>
sort of! but it applies only to bindings, not to values
02:04
<eemeli>
So like, really equal.
02:04
<nicolo-ribaudo>
What if it exported a live array of all the values
02:05
<Andreu Botella (🕑 JST, at TC39)>
cue adding quadruple equals to the language for stage 1
02:05
<eemeli>
Hey, you said it, I only thought about it.
02:08
<ljharb>
there's lots of equality symbols we could add! ≅ ≌ ≔ etc
02:09
<rkirsling>
puttin' the https://en.wikipedia.org/wiki/J_(programming_language) in JS
02:09
<Andreu Botella (🕑 JST, at TC39)>
hamburger operator
02:09
<Andreu Botella (🕑 JST, at TC39)>
oh, forgot this wasn't the temporal dead zone
02:09
<ljharb>
☰ ftw (i have that one on autocomplete, i'm incapable of typing the name of that sandwich now)
02:09
<rkirsling>
oh wait J is APL-like but ASCII
02:09
<rkirsling>
RIP my joke
02:12
<Chris de Almeida>
it's do be like that sometimes
02:13
<James M Snell>
Unicode U+2630 ... so close ... if only it had been U+2620
02:13
<bakkot>
is the thing being described here fuzzing or something else?
02:14
<bakkot>
I guess it's not quite fuzzing in that there is no randomness?
02:14
<nicolo-ribaudo>
If I understand correctly it's doing all possible combinations of some things, deterministically
02:15
<Richard Gibson>
are you really into the I Ching?
02:16
<ljharb>
lol nah it's the trendy menu icon on mobile apps before it was a grid of 9 squares
02:18
<bakkot>
we are very efficient this morning
02:19
<Richard Gibson>
right, I would describe it as a kind of metamorphic testing
02:21
<ptomato>
agreed, not fuzzing, though related I guess?
02:27
<bakkot>
return override does not add internal slots
02:27
<bakkot>
and cannot be used to add internal slots
02:27
<bakkot>
it can be used to add private fields, but those are slightly different
02:28
<bakkot>
all objects are created with an internal slot which stores a list of their private fields; that list is what gets updated when fields are added to an object, rather than the object itself getting a new slot
02:30
<Michael Ficarra>
thank you, I was trying to look through the spec to confirm that claim
02:34
<Michael Ficarra>
I think it's just editorial though and we would just stick the slot on every object in MakeBasicObject
02:34
<Michael Ficarra>
we wouldn't do a new thing (adding an internal slot to an object after its creation) unless we really had to
02:43
<Jake Archibald>
The title of this is incorrect on https://github.com/tc39/agendas/blob/main/2025/11.md "Into Locale Info API for Stage 4" - it made it hard for me to find
02:43
<Jake Archibald>
https://github.com/tc39/agendas/pull/2011
02:46
<rkirsling>
Frank's art is very intimidating :D
02:50
<Christian Ulbrich>
Clearly van gogh.
02:51
<Mathieu Hofman>
Just reviewing the note, the transcription today is missing quite a bit.
02:52
<jkup>
Does it require a point of order or is it ok now?
02:53
<Mathieu Hofman>
I'm not paying close attention enough, was just reviewing what I had said
02:55
<rkirsling>
tfw too efficient
03:38
<Chris de Almeida>
we are making good time thus far and have already been able to move some overflow topics into the schedule consequently, topics have been shuffled around quite a bit, so please consult for the latest information
04:13
<Aki>
I have been wondering what the use case is here
04:14
<Richard Gibson>
for maximumFractionDigits?
04:17
<Mathieu Hofman>
Not plenary related. Is there a way we could set proposal repos so that any tc39 member could create and push to branches (and probably branch protection to only allow direct push to main for champions). Would really love to avoid forking for simple contributions.
04:19
<Aki>
no sorry I think i was lagging a bit behind, it was a curiosity around trailing zeroes from the user code perspective. not meaningful for this technical discussion.
04:21
<Chris de Almeida>
gentle reminder: please do not tap on the microphones. 🙏
04:33
<rkirsling>
remind me whether we've discussed Array.zip before
04:33
<Ashley Claymore>
we have
04:33
<bakkot>
https://github.com/tc39/proposal-array-zip
04:33
<rkirsling>
excellent, thanks
04:34
<bakkot>
I personally can't actually imagine a use case for it though
04:34
<rkirsling>
in the sense that zip kind of implies you're gonna iterate?
04:34
<bakkot>
exactly once, yes
04:34
<rkirsling>
true that I can't think of a case where that wouldn't be so, offhand
04:35
<ptomato>
ljharb: Richard Gibson: I mean, we could just merge it literally now if you two are okay with it 😄
04:35
<ljharb>
go for it :-)
04:36
<eemeli>
Not supporting trailing zeros is the only blocker for a digit string representation of a number to be able to fully represent a numeric value together with a precision. Effectively we're trying to fix a small overlooked formatting bug here.
04:36
<Richard Gibson>
I'd like to give it one more look, but let's set a timeout for the end of this meeting
04:38
<Michael Ficarra>
oh god, who did this?
04:39
<ljharb>
(oh also, belated, for Joint Iteration, https://npmjs.com/es-iterator-helpers also implements it in quasi-spec text and it passes all tests)
04:39
<Chris de Almeida>
no snitching in plenary
04:40
<Michael Ficarra>
you should mention that in the test262 PR
04:40
<ptomato>
yes please do, I find that helpful at least
04:47
<Michael Ficarra>
certainly Guy's concerns would not affect Stage 3, they would be Stage 2.7
04:48
<Michael Ficarra>
I think he's maybe just not familiar with our process
04:49
<Michael Ficarra>
if anything, they sound more like concerns for which we'd consider reverting to Stage 1 to me
04:56
<bakkot>
the proposal is moving way from the thing on the screen
04:56
<rkirsling>
TIL "barrel file"
04:56
<bakkot>
iow I am confused by the observation that barrel files are bad for performance, given that the point of this proposal is, now they would not be bad for performance?
04:57
<bakkot>
if your problem with barrel files is that they have bad performance, making them not have bad performance seems like... it solves the problem?
04:57
<ljharb>
only if they were all created with defers all the way down
04:57
<ljharb>
which i think is a pretty big presumption
04:58
<ljharb>
iow, someone who's that vigilant would in theory be avoiding barrel files in the first place.
05:02
<Justin Ridgewell>
Barrel files are good for DX, bad for perf. Let's fix perf
05:07
<ljharb>
i don't agree they're good for DX
05:07
<snek>
i mean people using them in spite of the performance issues kind of proves the dx, no?
05:08
<eemeli>
Why do we have two @erights Mark Miller (Agoric) MMs on the Zoom call?
05:09
<Christian Ulbrich>
Second that. We can argue all the way about them, being devilish, fact is they are used pretty often.
05:10
<Chris de Almeida>
he likes to join via phone as well
05:11
<Christian Ulbrich>
eemeli: I think that has to do with space time.
05:13
<eemeli>
... and not e.g. with "them, being devilish"?
05:14
<Christian Ulbrich>
devilish referred to barrels and space time to two marks.
05:20
<Michael Ficarra>
agreed with @bakkot, in a vacuum we would treat it as if undefined was passed, not throw
05:21
<Michael Ficarra>
so diverging just to do the not-ideal thing seems not good
05:21
<rkirsling>
I too agree
05:21
<bakkot>
if we are branching on presence anyway I guess I don't really care about throw vs no-op
05:21
<ljharb>
it could also mean they're an attractive nuisance.
05:22
<Mathieu Hofman>
I thought most IsObject check for receiver were because some later steps are relying on looking up slots or similar on an object
05:25
<ljharb>
indeed
05:26
<snek>
idk what this means
05:28
<ljharb>
it means they're something people think they want but has subtle or unknown consequences they aren't aware of but wouldn't like
05:28
<ljharb>
iow, "choice" shouldn't ever be conflated with "informed choice"
05:28
<Michael Ficarra>
wait wtf there's slides now?
05:29
<bakkot>
not on the agenda there's not
05:29
<rbuckton>
{
  let bar = foo1.bar;
  if (bar) { ... }
}
{
  let bar = foo2.bar;
  if (bar) { ... }
}
05:30
<snek>
but those consequences are not to the developer, they're to the user.
05:30
<Michael Ficarra>
yes I literally do that because I hate having my bindings visible outside where they should be used
05:30
<Justin Ridgewell>
I wonder if V8 implemented during-function GC…
05:30
<hax (HE Shi-Jun)>
It seems Decl in cond proposal doesn't change anything compare to the version 5 years ago?
05:30
<snek>
depends on the function
05:30
<ljharb>
which is worse because in the priority of constituencies, users rank higher :-) also because the dev is even less aware of the harm they cause
05:31
<snek>
sure, i'm just clarifying that its still good DX, even if the UX is bad
05:31
<snek>
(and ideally, DX and UX should be aligned, but obviously that is not always the case)
05:33
<ljharb>
fair clarification
05:33
<ljharb>
i'd stretch to say that good DX that leads to bad UX is itself bad DX, because it begets angry users later
05:35
<Justin Ridgewell>
But we can make good DX also good UX
05:35
<snek>
i am absolutely shocked that anyone would want them to bind in other branches
05:37
<bakkot>

snek: I think this presentation didn't really cover all the contours. it's relevant that the proposal also includes an expression form:

if (let x = foo; condition(x)) {

} else {

}
05:37
<bakkot>
there's a lot more reason for x to be visible in the else here
05:37
<bakkot>
that said I still think it should not
05:37
<Justin Ridgewell>
I have certainly wanted to access the binding in the catch { } block
05:37
<snek>
no that should just be declared above the if statement
05:37
<ptomato>
I think Devin's a && b example is a convincing example why someone might want that
05:37
<bakkot>
also the fact that this is included is not at all obvious from the state of the proposal repo
05:37
<bakkot>
what if it's a using
05:37
<bakkot>
in fact the specific ability to put using here is the main reason I want this proposal at all
05:38
<rkirsling>
yeah I didn't realize the ; addition was coming
05:38
<snek>
then wrap it in a block
05:38
<snek>
that seems way simpler to understand
05:38
<bakkot>
do the wrapping
05:38
<bakkot>
it's not trivial at all
05:38
<bakkot>
you want disposal before the else
05:38
<Justin Ridgewell>
let foo = maybeThrows(); try { … } catch { console.log(foo) } is a non-starter.
05:38
<snek>
no i mean if you want to use it in both branches
05:38
<snek>
it should be above the else
05:38
<bakkot>
oh!
05:38
<bakkot>
yeah
05:38
<bakkot>
agreed
05:38
<bakkot>
strongly
05:38
<snek>
cool
05:38
<Justin Ridgewell>
I want try (let foo = maybeThrows()) { … } catch { console.log(foo) }
05:39
<rkirsling>
I'm fine with or without the ; but I feel strongly about the non-exposure to else
05:39
<Justin Ridgewell>
Doing let foo; try { foo = maybeThrows(); … } catch { console.log(foo) } feels icky
05:41
<nicolo-ribaudo>
The spec is only missing entering/exiting a new block scope right?
05:41
<nicolo-ribaudo>
Because right now the variables leak outside of the if/loop
05:41
<nicolo-ribaudo>
Even if they are defined in the head
05:42
<bakkot>
well, and like
05:42
<bakkot>
semantics for the if
05:42
<nicolo-ribaudo>
Oh right the semicolon version
05:42
<bakkot>
either version
05:42
<bakkot>
declaration have empty completion values
05:42
<hax (HE Shi-Jun)>
I agree with bakkot , for if (decl; cond) there are too many use cases require decl is availabe. But if no cond, there is no use case. This is the bad smell for the design.
05:43
<waldemar>
None of the new forms have semantics in the spec
05:43
<danielrosenwasser>
if (let { data, error } = ...; data) {
  // use data 
}
else {
  // use error
}
05:43
<bakkot>
danielrosenwasser: just put the declaration above the if in that case
05:43
<rkirsling>
wait what, analogous to for?
05:43
<snek>
this seems like a better motivation for the pattern matching proposal
05:43
<danielrosenwasser>
I was very surprised about else scope, but have written a good amount of code that uses it. It's nice.
05:43
<snek>
than trying to shove that into this
05:43
<rkirsling>
that's actually more of a head-scratching statement to me
05:44
<bakkot>
a for is an initialization which runs first, then a test, which runs second. this is the same pretty much! except the init has to be a declaration, but whatever
05:44
<danielrosenwasser>
The point is to avoid 2-3 data and errors :D
05:44
<bakkot>
... I don't understand? the obvious rewrite where you put it above doesn't have any more
05:45
<bakkot>
let { data, error } = ...;
if (data) {
  // use data 
}
else {
  // use error
}
05:45
<bakkot>

or if you really care about scope,

{
let { data, error } = ...;
if (data) {
  // use data 
}
else {
  // use error
}
}
05:45
<Mathieu Hofman>
are we talking about only have a single ; permissible. Because if you have multiple ; it gets confusing again compared to for
05:45
<hax (HE Shi-Jun)>
And I also think if we introduce such syntax, we should not copy c++, but swift/rust instead.
05:45
<danielrosenwasser>
I don't understand why the two (pattern matching and variable-scoped if) have to be at odds with each other
05:46
<bakkot>
yes, zero or one
05:46
<snek>
i'm fine with conditional declarations and pattern matching both existing
05:46
<snek>
just no conditional declarations being visible in alternatives. i am strongly against that.
05:46
<rkirsling>
I don't think it's fair to block this on a controversial sub-proposal of a Stage 1 proposal; even within the pattern matching space, I have very mixed feelings about is
05:47
<rkirsling>
this proposal is way more basic than pattern matching
05:47
<hax (HE Shi-Jun)>
I don't like the proposal in current form, but I will offline soon. If it was asked to enter stage 2, i will vote for no. I think we should wait for pattern match proposal.
05:48
<snek>
switch head visible to bodies is fine, that block encloses the cases
05:48
<bakkot>
I used to not really have an opinion on visibility, but with the inclusion of using I now feel strongly that the using binding must be disposed before the else, which implies the binding should not be visible in the else. rust actually changed their behavior to make disposal happen before the else! https://github.com/tc39/proposal-Declarations-in-Conditionals/issues/3#issuecomment-3458395454
05:48
<Michael Ficarra>
+1 Ron, I want to see the significant cross-cutting concerns fully explored before this proposal moves to Stage 2
05:48
<bakkot>
rust does not like to change things but this repeatedly caused nasty bugs in production
05:49
<rkirsling>
wasn't expecting a switch discussion 🤔 feel like ljharb would have some strong opinions
05:50
<rkirsling>
there it is
05:51
<rkirsling>
actually droppable braces is another argument against propagation to else, confusability-wise
05:51
<waldemar>
We should also add this to with statements. /s
05:53
<Christian Ulbrich>
I think the curly braces is a good argument, can't come up with an example, because I do not do my if-clauses w/o curlies. Hold on!
05:53
<Mathieu Hofman>
I find extra curly / blocks a visual nuisance, and avoid them unless really necessary
05:54
<rkirsling>
fwiw JSC has a hard "never braces for a one-line body", just so that we're clear on that being an intentional styleguide option
05:55
<snek>
is the queue advancing broken?
05:55
<ljharb>
i'll only grumble quietly as long as a consistent linter-enforced decision is made, but omitting braces - that's how you get gotofail
05:55
<Michael Ficarra>
no? there's just a lot of stuff on the queue
05:56
<snek>
oh i see, olivier started with the other topic
05:56
<snek>
i got confused and thought daniel was talking
05:58
<Christian Ulbrich>
For me it is about visual pattern recognition, whenever I see an if without curlies, I have to adjust and I do not want to that. I prefer solutions, that always work™.
05:58
<ljharb>
it also means more diff churn when converting between 1 and 1+ statement constructs
05:58
<Michael Ficarra>
@snek never misses
05:58
<ljharb>
same reason why arrow function args always have parens in the airbnb styleguide, even single-arg ones
05:58
<Christian Ulbrich>
This brings up another question, is there short-circuiting?
05:59
<bakkot>

dunno if Ben Lickly is in the chat, but the answer to the question is,

let match;
while ((match = tokenRegex.exec(input)) !== null) {
  // ...
}

vs

while (const match = tokenRegex.exec(input)) {
  // ...
}
05:59
<Christian Ulbrich>
I mean, what Gus said, is supposed to be the other way around... the condition must come after the declaration...
06:00
<Mathieu Hofman>
To clear up my statement, I don't want to add free-standing blocks inside/outside other blocks that are attached to statements
06:00
<Mathieu Hofman>
definitely dislike optional blocks, except for arrow functions
06:00
<ljharb>
sure, but that's an aesthetic preference that presumably is more important to you than the lexical availability of bindings?
06:01
<Andreu Botella (🕑 JST, at TC39)>
if it was something like a TDZ, it couldn't even be anything like a regular TDZ
06:01
<Aki>
No path to stage 2 right now but that felt like a good plenary conversation?
06:01
<Andreu Botella (🕑 JST, at TC39)>
because you'd have to somehow undeclare the value
06:01
<nicolo-ribaudo>
Putting curly braces is bad because it increases file size, making websites slower for users
06:01
<Jake Archibald>
Ashley Claymore: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz
06:01
<Mathieu Hofman>
The reason I dislike is because I associate blocks to control flow, and free standing blocks do not contribute to control flow (if you ignore labels)
06:02
<blickly>
That makes sense. Thanks for the example
06:02
<nicolo-ribaudo>
Re tdz: I think we should be careful with new TDZ after V8's feedback a whole ago
06:02
<Olivier Flückiger>
Ok, I did not think about the if (...; cond) syntax. In my mind the binding was just false in the else case. So with that I see the appeal of not having it in else....
06:03
<Olivier Flückiger>
but yeah, I am still worried about more TDZ
06:03
<Steve Hicks>
I'm confused, the if (...; cond) is exactly why it's useful to have the binding in the else - as in the better diagnostics example of why did the condition fail?
06:04
<Jake Archibald>
Steve Hicks: maybe if (const response = await fetch(…); response?.ok)? ignore me, I'm tired
06:05
<snek>
i think this motivates pattern matching, not having the binding available outside the consequent
06:06
<danielrosenwasser>
Pattern matching is cool, but other languages have this feature independent of pattern matching. There are plenty of times you want to bind a variable and check some specific condition that has nothing to do with truthiness or a type check.
06:06
<bakkot>

better diagnostics argues for, but using argues against, and I think is much stronger (since for diagnostics you can of course just put the binding outside). I want to be able to write this, and have the resource be disposed before the else. I invite you to rewrite it assuming that the binding lives through the else. I can't make it pretty!

if (using resource = getResource(); resource.needsUpdate) {
  resource.update();
} else {
  await postMessage('no updates required');
}
06:06
<Michael Ficarra>
I really hope the champion understands the breadth of work required to actually prepare this proposal for Stage 2. It's a lot.
06:06
<bakkot>

best I've got is this:

let neededUpdate;
{
  using resource = getResource();
  if (resource.needsUpdate) {
    neededUpdate = true;
    resource.update();
  }
}
if (!neededUpdate) {
  await postMessage('no updates required');
}
06:06
<rbuckton>
We discussed scoping awhile back in the pattern matching meetings with respect to is and let patterns. One of the problems with not having the binding be visible to an else has to do with inverting a condition, i.e., if you start with if (x) A else B and refactor to if (!x) B else A, you have to completely change how you write the code to bind the value
06:10
<danielrosenwasser>
It is a little funny that we might say "this thing can't be seen in an else but it's fine to see it in the default of a switch"
06:11
<bakkot>
I really think the argument from using against having the binding visible in the else is extremely strong, such that I would be opposed to the proposal going forward if the binding is visible in the else. Does anyone who thinks it should be visible in the else have thoughts on that specific topic?
06:11
<snek>
they're all standing in a circle talking rn
06:12
<danielrosenwasser>
I think I would have to do some reading on your concern there - is this comment the right starting point?
06:12
<bakkot>
the one above that, really, yes
06:12
<bakkot>
also https://github.com/tc39/proposal-Declarations-in-Conditionals/issues/12#issuecomment-3517821049
06:13
<rbuckton>

Or with a helper function:

function getResourceIfNeedsUpdate() {
  using stack = new DisposableStack();
  const resource = stack.use(getResource());
  if (resource.needsUpdate) {
     stack.move();
     return resource;
  }
  return null;
}

if (using resource = getResourceIfNeedsUpdate()) {
  resource.update();
} else {
  await postMessage('no updates required');
}
06:14
<rbuckton>

Or more generalized:

function holdResourceIf(acquire, test) {
  using stack = new DisposableStack();
  const resource = stack.use(acquire());
  if (test(resource)) {
    stack.move();
    return resource;
  }
  return null;
}

if (using resource = holdResourceIf(() => getResource(), res => res.needsUpdate)) {
  ...
} else {
  ...
}
06:15
<Ashley Claymore>
I shouldn't have said TDZ, really my Q should have been: would it be a syntax error to access the binding in the else? Or are the use cases conditional-shadowing-within-true-branch
06:15
<bakkot>
yeah, I think those examples make it very clear why it's better for the syntax to help out here
06:15
<Steve Hicks>
Ron mentioned pattern matching not supporting using - maybe this is where the two don't overlap? I assume pattern matching would allow scoping something to the entire block, so if you wanted access in both branches you could use that, and if you need using, you use this?
06:16
<rbuckton>
And that generalized form is not unlike what a condition variable might do.
06:16
<snek>
i don't think its ever a syntax error to reference an undeclared variable. it would be a reference error, unless something above the if had declared it.
06:18
<rbuckton>
IMO if you introduced bindings in if they would be similar to per-iteration bindings in a for loop, so scoped to the if statement (which might be considered to include the else clause)
06:19
<snek>
maybe if (var x = ...) can be the escape hatch for people who want the variable in their else branches
06:19
<bakkot>

I don't think there's good use cases but personally I would not make it a syntax error; just leave it to linters. I can imagine someone wanting to write

let data = whatever;
if (let data = updateOrNull()) {
  console.log('updated', data);
} else {
  console.log('not updated', data);
}

or something. probably they shouldn't but I don't think it's the language's place to forbid this

06:20
<danielrosenwasser>
It's a good point, it's a huge pain to make that resource dispose early. Definitely frustrating that the two use-cases are at odds.
06:20
<bakkot>
yeah but the use case when you want the binding visible is much, much easier to solve
06:20
<bakkot>
you just do the thing you'd do today
06:21
<bakkot>
whereas it's an actual significant upgrade on the use case where you want the binding not visible
06:21
<snek>
i don't understand why you would use a conditional binding but also want it to not be conditional. its not even the clearest way to write that code
06:23
<Olivier Flückiger>
let x = true;
if (let x = false) {} else {log(x)}
06:25
<rkirsling>
that is some yucky code
06:26
<snek>
you can write let i = 4; for (let i = 0; i < 10; i++) {}
06:27
<bakkot>
let e = 0;
try { throw 1; } catch (e) { console.log(e) } finally { console.log(e) }

that's just how bindings work!

06:27
<Olivier Flückiger>
sure, I am saying that it is easier to understand visually where you refer to which binding...
06:28
<eemeli>
Why are we still doing paper attendance sheets?
06:28
<Olivier Flückiger>
(if it exists in the else)
06:28
<nicolo-ribaudo>
Programmers are known for making computers not work
06:29
<Olivier Flückiger>
Btw. we have a similar case in for. If the following was valid syntax: for (let x = false; x; false) { } else { x }, then x would be out of scope in the else case. But it is not valid syntax...
06:29
<waldemar>
How did I get onto the queue twice?
06:29
<Christian Ulbrich>
twitchy fingers!
06:29
<snek>
probably request retry with no protection for that
06:29
<Christian Ulbrich>
or - highly unlikely - a race condition in TCQ.
06:29
<waldemar>
I'm not that fast at typing.
06:32
<Christian Ulbrich>
FWIW if you accidentally double-clicked the submit, it gets send twice, because there is no logic in TCQ preventing that.
06:33
<rkirsling>
ooh
06:33
<rkirsling>
see now that deserves a bug report
06:34
<Chris de Almeida>
because Ecma, that's why. do not question the Ways of the Ancients
06:34
<eemeli>
Oh, but I do.
06:34
<Chris de Almeida>
over-eager web sockets
06:34
<Aki>
Samina and I are choosing our modernisation battles carefully. Neither of us cares to die on the hill of paper sign-in sheet.
06:35
<Chris de Almeida>
what's crazy is that the paper sheet gets mailed out to all remote attendees to sign and send back to Ecma
06:36
<snek>
and they don't even include postage
06:39
<Christian Ulbrich>
Ugh. Never got them.
06:39
<Rob Palmer>
also it helps me get accurate numbers for the social dinner
06:41
<eemeli>
At least one physical sheet is now filled out completely next to Shane.
06:44
<rbuckton>
Btw. we have a similar case in for. If the following was valid syntax: for (let x = false; x; false) { } else { x }, then x would be out of scope in the else case. But it is not valid syntax...
Since that syntax doesn't exist, it's arguable in either direction.
06:46
<Ashley Claymore>
https://es.discourse.group/t/proposal-for-else-also-while-else-statement/934
06:46
<rbuckton>
The only other statement with split syntax like this is do...while, but there's no variable scoping involved
06:46
<ljharb>
there would be with the relevant proposal, tho
06:46
<bakkot>
try {} catch (e) {} finally {}
06:47
<ljharb>
try {} catch (e) {} finally {} andthen {}
06:48
<rkirsling>
finallyer
06:48
<rbuckton>
IMO, catch is a bit of a weird case, and finally is executed in both branches so it's not indicative
06:48
<Ashley Claymore>
for x in range(3):
    print(x)
else:
    print('Final x = %d' % (x))
06:49
<Ashley Claymore>
TIL
06:49
<Ashley Claymore>
(I've done almost zero python dev)
06:50
<Olivier Flückiger>
haha, as a C programmer I was expecting it to print final = 3
06:51
<rkirsling>
I did not realize that was in Python
06:51
<Ashley Claymore>
I wasn't expecting the else to run at all. I thought for-else would be for when the loop block never runs
06:52
<rkirsling>
oh wow yeah
06:52
<nicolo-ribaudo>
"Do this in an infinite loop, or else if you cannot go forever do this"
06:52
<rkirsling>
that's a broken use of a keyword if it doesn't mean that
06:53
<Ashley Claymore>
halt-or-else
06:53
<Michael Ficarra>
that would be identical to just putting it after the loop?
06:53
<rkirsling>
yeah but it's less a utility question and more a "what does the word else mean" question
06:54
<rbuckton>

if using had stuck with Java's try-with-resources then we might have a case. IIRC, In Java:

try (FileReader r = new FileReader(...)) {
  ...
}
catch (IOException e) {
  // r is not reachable
}

But control-flow based on exceptions isn't quite the same as if...else

06:54
<rkirsling>
they should've chosen a different word
06:54
<rkirsling>
namely finally
06:55
<bakkot>
it only runs if the loop does not early exit
06:55
<bakkot>
it's for searching
06:55
<Ashley Claymore>
ah thanks. so break would skip the else
06:56
<bakkot>
for x in range(3):
  if x == 2: break
else
  print('not found')
06:56
<bakkot>
yeah
06:56
<bakkot>
it make sense in this context and only this context
06:56
<bakkot>
it's a bad choice of keyword though
07:08
<Chengzhong Wu>
should the tcq be advanced?
07:11
<Michael Ficarra>
"some files don't use UTF-8" is extra relevant at the Japan meeting
07:16
<Justin Ridgewell>
I think we should just assume UTF-8, and let import bytes to get a different encoding.
07:21
<Michael Ficarra>
consider windows-1252 @sffc
07:28
<nicolo-ribaudo>
Would it be simpler to merge the proposals at some point?
07:28
<nicolo-ribaudo>
To have a single PR
07:28
<nicolo-ribaudo>
The implementation would probably also be done at the same time
07:29
<ljharb>
i don't think "one PR" is of much value personally
07:29
<nicolo-ribaudo>
It's for the champions, they will conflict in half of their changes
07:29
<nicolo-ribaudo>
And they are both incredibly small, reviewing them together would not be a burden
07:29
<ljharb>
i'm happy to do the rebasing, nbd
07:29
<ljharb>
either way
07:30
<Olivier Flückiger>
Hmm, ok, I am confused about the import text proposal I think. A string can only contain utf-8 chars right now, right? at least string literals. So what would happen if you create a string with non utf-8 chars with import text?
07:31
<snek>
no, string literals in javascript are not limited to utf8
07:31
<nicolo-ribaudo>
String literals allow unpaired UTF-16 surrogate pairs
07:31
<nicolo-ribaudo>
But I think that's beyond the point of the discussion
07:31
<ljharb>
'\xc3\x28' is not UTF8 and is a valid JS string, eg (i believe)
07:32
<Michael Ficarra>
JavaScript strings are sequences of UTF-16 code units (numbers between 0 and 65535, inclusive)
07:32
<nicolo-ribaudo>
The question is: given some bytes, do we extract the code units out of them with UTF-8 rules, or do we allow following multiple encoding rules?
07:32
<Michael Ficarra>
I'm surprised more people don't think of them this way
07:33
<Michael Ficarra>
That's not the question though? It's just up to the host.
07:33
<Olivier Flückiger>
https://tc39.es/ecma262/#sec-literals-string-literals
07:33
<nicolo-ribaudo>
The question was whether we want to give host guidance for these imports, no?
07:34
<Olivier Flückiger>
"A string literal is 0 or more Unicode code points enclosed in single or double quotes. Unicode code points may also be represented by an escape sequence."
07:34
<ljharb>
they already have to do that for modules, no?
07:34
<snek>
the normative requirement should be exactly "construct a javascript string". how the host implements such a construction is out of scope for ecma262 itself
07:34
<jkup>
the transcription quality is struggling.. not sure if that's worth stopping or just finish the rest of today?
07:34
<nicolo-ribaudo>
Let's say you have an encoding where A is 0x00, B is 0x01, ..., and you import a file that contains 0x00-0x01 that has that encoding. Is it fine if it results in the string "\u0000\u0001", even though it was meant to contain the string "AB"?
07:34
<Michael Ficarra>
Who is asking that question?
07:34
<nicolo-ribaudo>
That's what I understood the question to be
07:34
<nicolo-ribaudo>
Shane?
07:35
<nicolo-ribaudo>
If not, I did not understand what Shane was saying
07:35
<ljharb>
of course, you made your own homegrown encoding. you read it as text or bytes and interpret it yourself in that case, no?
07:35
<Michael Ficarra>
you and I both know literals are not the only way to construct strings
07:36
<nicolo-ribaudo>
It was for an example, assume it's some other known encoding
07:36
<nicolo-ribaudo>
To be clear, I want it to be UTF-8 only. I'm not representing my opinion
07:36
<nicolo-ribaudo>
It's what I got from the discussion
07:37
<Michael Ficarra>
I think the question was more like "is there something better we can do when the host uses the wrong encoding to decode the text?" and the answer is pretty easily "no", right?
07:38
<sffc>
If what people are saying about JSON imports being required to be UTF-8 is true, then a JSON file that is encoded on disk as UTF-16 BE will start with a NUL byte (or perhaps a BOM), which is invalid JSON, so the error happens early. But with import text, the conformant behavior would be to convert those bytes to replacement characters, and developers won't find out that there was an encoding problem. Implicit wrong encoding problems cause errors across many generations. Everyone here has seen garbled text on websites that results from the wrong encoding being used when reading bytes from a database or data file.
07:39
<nicolo-ribaudo>
CSS imports also assume UTF-8, but CSS is much more lenient and doesn't throw an error as far as I know
07:39
<nicolo-ribaudo>
I mean type: "css"
07:40
<Michael Ficarra>
@sffc that's specifically with a mix-up between UTF-16LE and UTF-16BE, but there are many other encoding mixups that will cause mojibake in your string but overall still be valid JSON
07:40
<snek>
i'm very confused about where utf-8 is coming into this conversation for type text, is it because of type json?
07:40
<Michael Ficarra>
that's why I said consider windows-1252 and code points between 0x80 and 0xFF above
07:41
<sffc>
JSON is itself a text-based encoding. The first code point is { or [ or " or another syntax character, and it has the same encoding as the string values contained inside the JSON. This is different from binary encodings.
07:42
<nicolo-ribaudo>
But you need to first get that text from some bytes, no?
07:42
<nicolo-ribaudo>
It's bytes->text->json. You are saying "it's fine if bytes->text does the wrong thing because you are catching it at the next step", but MF pointed out that you won't always catch it at the next step
07:44
<Michael Ficarra>
yes and some encodings encode { and [ and " the same as another encoding but encode £ and æ the same
07:44
<sffc>
Yeah, like Latin-1, but not UTF-16
07:44
<Michael Ficarra>
so it's still valid JSON but the string data of the string that's encoded in the JSON is different because the wrong encoding was used to decode the JSON
07:45
<Michael Ficarra>
no, a latin-1 and UTF-16 mixup would not have this kind of behaviour
07:45
<Chris de Almeida>
we have been doing so well on time and have had to move a lot of topics up. the downside is at this time, the day 2 and day 3 schedules are in rough shape. we will update, but please be patient
07:45
<snek>
i feel like this conversation is being confused by the difference between abstract strings and utf8/utf16/etc strings
07:46
<Michael Ficarra>
wtf is an abstract string
07:46
<sffc>
A UTF-8 JSON parser might not fail on JSON stored as Latin-1. It should fail on JSON stored as UTF-16
07:46
<Michael Ficarra>
agreed, and?
07:47
<sffc>
And, then if the JSON file is encoded as UTF-16, then the error happens early
07:47
<Michael Ficarra>
a windows-1252 JSON parser will accept all JSON stored as latin-1 but some of it will have strings in the result that are different
07:47
<snek>
its not a thing in computer memory, its the theoretical characters. like the mathematical concept of numbers vs the concrete implementation of floating point.
07:47
<Michael Ficarra>
meaning there are no early errors
07:47
<snek>
idk if there's a better term
07:48
<Michael Ficarra>
it's just as fraught as text
07:48
<Michael Ficarra>
USV strings, or sequences of code points (ish)
07:48
<ljharb>
(ps, "the iterator protocol is crazy slow" is a strong use case for Array.zip)
07:49
<Michael Ficarra>
compelling case for engines to actually optimise their impleentations
07:49
<snek>
sequences of infinitely large code points, i guess? its not just restricted to how many characters there are in utf32 for example
07:50
<Michael Ficarra>
Unicode only defines 0x110000 code points
07:50
<snek>
i wouldn't think about it in terms of computer memory or numbering characters
07:50
<Michael Ficarra>
so you mean... text?
07:50
<sffc>
You're saying that, since Windows-1252 encodes JSON syntax characters the same as UTF-8, then import type JSON gets a late error, which is the same as what will happen with import type Text. I agree that this is a true statement
07:50
<snek>
if that's the term for it
07:51
<Justin Ridgewell>
OMG byte offset is awful
07:52
<ljharb>
i'm not gonna hold my breath
07:52
<nicolo-ribaudo>
Process-wise, sffc is there any change you maybe would want to see in the proposal itself, or is this about guiding the HTML integration?
07:53
<sffc>
The "true statement" above doesn't address my concern, other than asserting that one of the most likely environments where there would be an error (reading text files on Windows) already has this behavior with other import types
07:54
<Michael Ficarra>
@sffc can you state your concern? @nicolo-ribaudo and I were unsure about what it was
07:56
<sffc>
In plenary, I made an assertion that import type text has late-error cases that other import types don't have. The statement about Windows-1252 reduces the number of cases where this happens, but it is still happens for encodings like UTF-16 BE.
07:58
<Michael Ficarra>
if something "sometimes has a problem", it means we always need to consider the problem if we want to do it right
07:59
<Michael Ficarra>
so given there exists at least one pair of encodings where this problem could happen, it's just as important of a problem as the text mixup
15:40
<bakkot>
I really do not understand the conversation above. There's no requirements that hosts even represent importable resources as bytes at any point. It would be perfectly valid for a host to allow you to do import text from 'my sample text' with { type: 'text' } and have that result in the text 'my sample text', for example.
15:41
<bakkot>
Some hosts do represent resources as bytes, in a variety of ways, but that's entirely out of our scope
17:46
<bakkot>
More realistically, something like Graal or other cross-language interop runtimes could allow consumers to define text to be importable from JS, and these would be presumably defined in terms of strings, not bytes. Compartments could be extended to do something similar. There's just no relevant notion of "encoding" a string to be imported from the perspective of these sorts of things. It doesn't make sense for the ES spec to concern it with the subset which happen to have the host doing translation from bytes.
17:47
<bakkot>
I'm sure HTML will specify how bytes from the network are translated to text to be imported, because it's a host, which is the appropriate layer to define those semantics.