Annex B.3.3 substantially changes strict vs non-strict semantics

# Kevin Gibbons (9 years ago)

I'm not sure if this is well-known; it was certainly surprising to me.

Consider the following program: `let func = () => 0;

(function(){ { function func() { return 1; } } return func(); })();`

The return value of the second function depends on whether this program is evaluated in strict mode or not. In strict mode (for example, as a Module), annex B.3.3 does not apply, so it returns 0. In sloppy mode (for example, as a Script), annex B.3.3 applies and it returns 1.

You can see how the semantics change on the scope analysis demo we've just put up at shift-ast.org/scope.html?code=let func %3D () %3D> 0%3B (function(){ { function func() { return 1%3B } } return func()%3B })()%3B#demo : as a Module the last func identifier refers to the outer func, and as a Script it refers to the inner one.

Is it considered acceptable to have such large changes in strict vs non-strict semantics for unremarkable code? If not, should B.3.3 be made to apply in strict mode?

# Mark S. Miller (9 years ago)

On Tue, Jan 19, 2016 at 9:54 AM, Kevin Gibbons <kevin at shapesecurity.com>

wrote:

I'm not sure if this is well-known; it was certainly surprising to me.

Consider the following program: `let func = () => 0;

(function(){ { function func() { return 1; } } return func(); })();`

The return value of the second function depends on whether this program is evaluated in strict mode or not. In strict mode (for example, as a Module), annex B.3.3 does not apply, so it returns 0. In sloppy mode (for example, as a Script), annex B.3.3 applies and it returns 1.

You can see how the semantics change on the scope analysis demo we've just put up at shift-ast.org/scope.html?code=let func %3D () %3D> 0%3B (function(){ { function func() { return 1%3B } } return func()%3B })()%3B#demo : as a Module the last func identifier refers to the outer func, and as a Script it refers to the inner one.

Is it considered acceptable to have such large changes in strict vs non-strict semantics for unremarkable code?

That is the right question. The answer is yes. Sloppy mode exists only to avoid breaking crappy legacy code, rather than to have any coherent semantics. All new code should be strict, especially if you want it to work or to have anyone understand it.

If not, should B.3.3 be made to apply in strict mode?

ABSOLUTELY NOT!

(Or rather since the answer to your first question is yes, and you started this one with "If not", the answer to this one is Mu ;).)

# Andrea Giammarchi (9 years ago)

FWIW I think that's expected. Strict mode would throw otherwise but of course if you have an outer scope reference to whatever you are invoking that's indeed what you invoke.

Making it behave similarly in both strict and non strict would be a mistake for the existing sloppy code but I agree that in strict mode that should probably warn (at least) regardless.