tc39 / proposal-do-expressions

Proposal for `do` expressions
MIT License
1.11k stars 14 forks source link

do expressions can introduce strict mode #56

Open bakkot opened 3 years ago

bakkot commented 3 years ago

This issue was posted by @michaelficarra on my fork of the repo, which is what I presented to the committee. I'd like to centralize the discussion here, so I'm reposting it, though see comments in that thread. Original issue follows:


From #tc39-delegates IRC:

14:48:41 michaelficarra I kind of prefer it introducing a strict context actually 14:48:52 michaelficarra it's a new feature, who would want to write sloppy code inside a new feature? 14:49:03 ljharb yeah i kind of like that too 14:49:22 ljharb historically the pushback to that is "refactoring hazard", but somehow that was fine for Modules and class 14:49:31 michaelficarra yeah 14:49:36 ljharb (ie, async function, generators, etc weren't auto-strict for that reason, iirc) 14:50:17 michaelficarra that makes sense though since functions don't auto-introduce strict and they're just function variants 14:50:22 michaelficarra this is a new kind of thing, like class 14:50:34 michaelficarra totally fine for those to introduce strict mode 14:50:39 ljharb fair 14:50:57 rkirsling in a way, given that async function is a kind of function it makes sense that it would need to use 'use strict'' whereas do {}, like class {}, wouldn't have a directive within it 14:51:11 michaelficarra ^ exactly 14:51:18 rkirsling so I would agree with strict-only unless we can think of a way in which it is harmful

/cc @ljharb @rkirsling

ljharb commented 3 years ago

It would be nice if all new constructs, just like classes, were auto-strict. Sloppy mode is bad, and if the refactoring hazard from Scripts to Modules and functions to classes is acceptable, then this should be too.

bakkot commented 3 years ago

My position on this is that only things which can be plausibly understood as new function or top-level contexts should introduce strictness. I don't think it's a good idea to opt people in to strictness in the middle of random expressions.

And for do expressions in particular, I'd like to keep the correspondence between stmt; and (do { stmt; }) as close as possible (except of course that the latter would have its own scope). That's a much tighter relationship than the relationship between function bodies and class bodies; that refactoring requires substantially more changes, in general.

nicoburns commented 3 years ago

Another option would be to only allow use of do in contexts which are already strict. So do { ... } in sloppy mode is a hard error (could this be made a syntax error?), and you need to add "use strict" or similar in order to proceed.

josephrocca commented 2 years ago

Another option would be to only allow use of do in contexts which are already strict.

I'd definitely prefer to have the context automatically upgraded to strict, rather than to have an error thrown if I had to choose between the two. I like the simplicity of a simple <script> /*some code here*/ </script> dropped in my HTML, and having to forever add "use strict" to get modern JS features would make me sad.

There might be some big trade-offs that I'm not considering here, but in general I don't like the idea having to remember the set of features which require "use strict". I'd probably just end up having to add "use strict" to all my non-module inline script tags, and at that point I'd be wishing it just auto-upgraded the context to strict when necessary so my code would be cleaner and so I wouldn't need to remember to add "use strict" all the time.

I think it could also be confusing for newbies - adding some valid, modern JS code to a script tag, and then having it throw an error saying something about needing a mode that is strict - only to eventually find out that, actually, for some JS code you need to write "use strict"; at the top of the <script> to get it to work. I can imagine my past coding students being very confused and frustrated by this.

bakkot commented 2 years ago

I think it would be a considerable disservice to newbies to ever suggest they write code in a <script> tag without "use strict" at the top, so I'd hope that doesn't come up very often.

Jack-Works commented 2 years ago

you can write <script type="module"> 👀

josephrocca commented 2 years ago

@bakkot Maybe. I don't think I've ever written "use strict";, but maybe learning JS would have been easier if I had - I'm not sure. I'm fine if the feature opts people into strict mode - but if it does, then I think it should upgrade automatically to avoid extra boilerplate code when writing a simple <script>.

@Jack-Works I very often write code like the example below, which delights me (as someone who mostly works on small demos and stuff - like this, for example), but perhaps makes others sick. It doesn't work with modules for obvious reasons.

<input id="nCoresEl" type="range" value="1">
<script>
  nCoresEl.max = navigator.hardwareConcurrency;
  ...
</script>

I like the idea of keeping vanilla HTML "writable" (that is, simple to write), and I know I'm not going to convince anyone here that they should write code like above, but I guess I'm just not a fan of adding extra boilerplate in the "general" case. I feel like if some very "core" JavaScript syntax throws an error in basic script tags, then we tie ourselves into some irreversible boilerplate that <script>s will, from then on, always need. The trade-off calculus would probably come out different for me if this were a less fundamental JS feature.