Closed jridgewell closed 4 years ago
This only makes sense if you think of the rewrite of a ??= b
as a ?? (a = b)
instead of a = a ?? b
. I think most people will think of it as the latter. My understanding is that they're equivalent (for any a
that participates in FNI, ignoring with
). Because of this, I think we could have a valid argument both for and against FNI.
Makes absolute sense to have function name here, but as @shapesecurity mentioned most of us would interpret a ??= b
as a = a ?? b
unless otherwise mentioned or people understand that this behavior is for anonymous functions.
ftr you don't need an IIFE to work around it, you can do (0,function () {})
I could go either way on this, but I have a slight preference for it not using the name.
In the same way that
let x = false || function() { };
let y = true && function() { };
let z = null ?? function() { };
don't assign the name, I don't think this should either. I feel like the only time we should use the variable name for the function name is if it's completely straightforward (e.g. let foo = function() { };
).
Ugh I guess we really shouldn't ignore the existence of with
...
Given this observable equivalence for get/set invocations:
let a = true;
with ({
get a() { console.log('get a'); return a; },
set a(x) { console.log('set a'); a = x; },
}) {
// this line
a ||= function(){};
// is observably equivalent to this line:
a || (a = function(){});
// not equivalent to this line (the setter is invoked):
a = a || function(){};
}
then I'd expect their handling of FNI should be the same.
let a = false, b = false;
with ({
get a() { console.log('get a'); return a; },
set a(x) { console.log('set a'); a = x; },
get b() { console.log('get b'); return b; },
set b(x) { console.log('set b'); b = x; },
}) {
a ||= function(){};
b || (b = function(){});
}
assert.eq(a.name, 'a');
assert.eq(b.name, 'b');
I don't see why the same sequence of get/set invocations should have any impact whether or not the function gets an inferred name. a || ((a) = function(){});
triggers the same proxy traps, but doesn't assign a function name.
@anba My thinking is that users will think of the syntax introduced in this proposal as simple sugar for one of a = a || b
or a || (a = b)
(for simple LHSs). When choosing between which of those two they might think of, we would want to take into account the semantic parity. Taking that into account, the most similar desugaring is a || (a = b)
, so we should match that with FNI as well.
if the left side is an identifier and the right side is an anonymous function, the function should have the name, regardless of what the operator is.
Context: https://github.com/babel/babel/issues/11362
As currently spec'd, Logical Assignment does not assign a name to anonymous functions. Consider:
This currently should log
undefined
. But I think it'd be totally reasonable for this to logfoo
instead.Babel hits this issue with its transform:
That
(foo = function() {})
will assignfoo
as the name for the anonymous function. We can work around this by using an IIFE to indirect. But I don't think the name hurts here.