-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should eval?.() be direct eval? #2062
Comments
My understanding of the factors to weigh:
|
It wasn’t exactly intentional; rather, it was intentionally unintentional. When I wrote the spec, I deliberately chose to ignore what I considered to be a non-issue. IOW, the currently specced semantics is a consequence of how direct eval was specced at the time of introduction of optional chaining, not a deliberate decision. |
FWIW SpiderMonkey was able to quickly change from direct to indirect eval, because for us it was a one line change: mozilla/gecko-dev@8cc6255 I understand that other implementations may have more trouble here. Unless someone else from the SpiderMonkey team (cc @codehag) has any concerns about the change to indirect eval, I'll probably won't revert the commit for now, so we can report to TC39 if we encounter any web-compatibility issues (, which I expect to be rather unlikely 😄). |
I am following it. Will report back if there are any issues. I also do not suspect that there will be any. |
FWIW I'm happy with |
@anba, @codehag: Fair enough—this discussion is definitely predicated on both ways still being web-compatible, so if we found that not to be the case, that'd be the strongest deciding factor! @claudepache: Thanks, that's a really helpful clarification. So then it's much like the @littledan: Adding more direct eval cases is certainly not a goal in itself, though it seems that not doing so might be considered a goal among certain delegates. My own goal here is really just to have the discussion now that we forgot to have during review, and I'm trying to evaluate by priority of constituencies. To resummarize in paragraph form: If |
FWIW it looks like updating V8 to make this an indirect eval would be a single-line-ish change. |
JSC would be as well; I'm sorry if I made it sound like this would imply a major refactor. I just want our decision here to be conscious and not accidental. |
No, Note that |
A third option is to make |
@claudepache I do see your point in analogizing with |
wouldn't that mean that |
fwiw |
FWIW, babel and TypeScript also transpile |
Note that Babel's behavior was accidental (but my opinion matches our implementation: |
cc @erights I second @littledan's comment. Indirect eval should be just fine in this case. |
@claudepache says
I agree. I suggest the "Principle of Least Damaging Surprise" as a name for the principle we followed for the There's a syntactic construct S that some would guess has meaning M1 and some would guess has meaning M2.
In this case, I don't think it matters much because I don't think anyone will naively write this. However, even if the effect is minor, syntax error causes the least damage. |
While I think the error approach is worthy of mention, I don't think I agree that it's less surprising in this case. It might have potential to be more surprising here, for the reason that @ljharb was approaching above—even in strict mode, I can freely set Given that |
@rkirsling Whatever we do, it will be more surprising for someone. The idea of the syntax error, is not to make the behaviour less surprising, but to make it impossible to get wrong in case they have the wrong intuition. The fact that it is an early error means that there is very low chance that it will appear by accident in production. |
I'm not sure whether direct eval or indirect eval is the correct question. As specified,
So it isn't choosing between a direct eval or an indirect eval, it is choosing between a direct eval and a normal call. It might be an attempt to call something that is not callable (eg, So, what does a normal programmer expect when writing What should they expect if they intentionally wrote The simplest thing from a programmer's perspective is to just threat ?. in a call as an orthogonal feature. Any special case treatment, including a syntax error for eval just adds to the already too large set of arbitrary special case rules that JavaScript programmers need to learn. |
Well stated. @allenwb's argument here matches my thinking exactly. |
I am not sure we can assume what they want for indirect or direct evals in here.
If I understand correctly, we are setting some sort of a default path for usages of eval calls that are not straight up I don't worry too much which direction we take here, but I believe we are creating an exception if we change the spec, rather than enforcing an intended default behavior. Today, what we have as default is: direct eval is only direct calls to a name If we change the specs as proposed, we add a new specific rule such as: direct eval is also possible through optional chain. We remove something out from the "everything else" bag of indirect eval. On another note, I don't think it's ECMAScript's responsibility to guard developers against |
No, I don't think you understand how "direct eval" is statically recognized by the specification in 12.3.6.1. The guard that is used to recognize a direct eval is:
The intent of this guard is to ensure that the MemberExpression expression that provides the function value is exactly the Identifier If the evaluation abstraction operation for MemberExpression?.(x) uses the same guarded logic as 12.3.6.1 then |
I understand how it is spec'ed and I'm glad implementations are consistent, as anything from my Test262 perspective. My point of view here is as a web dev, out of my personal intuition, putting any spec work aside and having close to 0 experience as implementor. As a web dev, writing JS code, I'd expect As I mentioned, my intuition goes as we are proposing an exception for the general rule where direct evals were limited to roughly I'm not objecting to this change, but I don't think it's the best path. |
I think it's very hard to say how developers expect On one side, I believe many developers simply explain On the other side, some developers (especially those have much deeper comprehension of direct/indirect eval) will expect it as indirect eval because they understand direct eval as an operator (think Both side seems reasonable, so my first feeling is we should make it as syntax error. But we already can write If we couldn't make it a syntax error, I guess maybe we can make |
Lending further support for syntax error, notice that let eval = () => {}; eval() is already a syntax error in strict code. |
The syntax error in strict mode comes from the assignment, not the CallExpression. If just the assignment was done within non-strict code, the strict mode CallExpression would go ahead and invoke the arrow function. I don't see how the strict mode restriction on assignment to A more relevant consideration may be consistency with other syntactic forms that look like calls. For example, |
In that case tho, |
Consider So I think make it a syntax error may be the best option. |
First, I'll take this rare opportunity to say " For programmers just writing normal strict code, it would be very rare for Programmers who bind |
I agree that it is doubtful whether there is any reasonable reason for anybody to write Quote myself from #2062 (comment)
This basically a complexity budget issue. Don't make the language unnecessarily more complex by adding a nanny-style error. Better for linters to have a rule about |
Thank you. As you appreciate, I love arguments from complexity budget. I agree that a SyntaxError here makes the spec and the formal language more complex. However, from the point of view of the programmer, coping with a system that silently deviates from programmer expectation is way more complex than coping with a syntax error. I also agree that this is a dangerous argument if overused. The key here is that even sophisticated programmers, knowing all the rest of the language well, will arrive at different expectations. If one of these were clearly dominant over the other, once explained, I would probably advocate that. But if neither dominates, better to stop the lurking surprise before runtime. I should also say that I don't really care about this one specifically. Approximately no one will write -2**3 I will certainly not block consensus on this issue. Whatever everyone else can agree on is fine enough with me. |
To me, the crux of
We also had two separate camps surrounding how |
[off topic] Yeah, I have to say I'm one of them. I've heard a programmer complain that he have to explained it 4 times to the reviewers for
I may already comment about linters many times: every new linter rule have cost (development, documentation, discussion, adoption, configuration, deployment, etc.) in the whole js ecosystem, which have a much large scale than tc39, so the cost is much bigger than we realize. |
Closing; we decided to leave the spec as-is in today's meeting. |
So |
i would not expect |
It seems the meeting notes shows some delegates object direct eval because of
But |
@hax the objection is strictly to |
I would classify it as, making this one direct would force the pipeline case, as well as unknowable future cases, to all be direct as well; leaving this indirect still leaves the design space open. |
In my opinion, we are just adding one and one ad-hoc rules which hard to infer and remember. |
I kinda agree. I had assumed from the meeting that we had settled this for all the new operators but it sounds like that's not the case?
That's not quite a general rule, if you replace |
That was my understanding. This sets precedence that new call syntaxes that invoke |
My mistake, that seems fine to me too. |
Issue-ization of tc39/test262#2667 (comment).
eval?.()
is specified as indirect eval, which is evidently intentional, but speaking as a reviewer and implementer, I'm not sure how many of us understood this to be the case.In particular, JSC / SM / V8 all implemented and shipped what we expected the spec to say—i.e., that "code with
?.
behaves the same as code without it when the LHS is non-nullish"—so we have a divergent reality here.Whichever way we resolve this, I think it's necessary to have a proper discussion about it.
I'll also create a PR for moving to direct eval, at least for demonstration's sake.
The text was updated successfully, but these errors were encountered: