Skip to content

Function statements in strict mode #118

@r-e-d

Description

@r-e-d
Contributor

In strict mode, function statements are only allowed at the top level of a script or function (source). Currently acorn accepts code that does not follow this rule.

For example, this code should throw a SyntaxError :

"use strict";
if (true)
  function bar() { }

Activity

getify

getify commented on Aug 28, 2014

@getify

I don't think that's accurate. In fact, I believe as of ES6, this is officially allowed.

Trying it in Chrome:

function foo(a) {
   "use strict";
   if (a) {
      function bar() { console.log(a); }
      bar();
   }

   bar();
}

function bar() { console.log("oops"); }

foo();           // "oops"
foo("hello");    // "hello"   "oops"

I think the difference is that if (a) function ... is not allowed, but if (a) { function ... } is.

RReverser

RReverser commented on Aug 28, 2014

@RReverser
Member

@getify Agree, but weird that MDN page and ES5 standard mention that this should be prohibited (while browsers don't).

getify

getify commented on Aug 28, 2014

@getify

Let's ask @allenwb or @rwaldron for clarification. :)

r-e-d

r-e-d commented on Aug 28, 2014

@r-e-d
ContributorAuthor

@getify, if i copy/paste your foo function in the console in Chrome (or Firefox), I get "SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function".

getify

getify commented on Aug 28, 2014

@getify

@r-e-d

Could be that I'm running Chrome canary with ES6 stuff turned on? Shrugs.

chrome screenshot

allenwb

allenwb commented on Aug 28, 2014

@allenwb

First ES5 and ES6 are different.
In ES5 strict mode, all non-top level functions declarations (by informal agreement among browser implementators, not by spec. ) should be illegal.

In ES6, function declarations are legal (regardless of mode) in blocks. In strict mode, function declarations are still illegal as single statements such as if (true) function foo() {};. In theory, the same applies to non-strict mode, but for browsers specifically, Annex B rules apply: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-block-level-function-declarations-web-legacy-compatibility-semantics and http://people.mozilla.org/~jorendorff/es6-draft.html#sec-functiondeclarations-in-ifstatement-statement-clauses.

There is no particular reason to assume, at this point in time, that Chrome, FF, MDN, or anything else has yet to get this all correct.

getify

getify commented on Aug 28, 2014

@getify

Thanks for the great clarifications, @allenwb. I suspected exactly that, but you're the authority. :)

From your perspective, do you think a parser should disallow things that the spec allows (or allow things the spec disallows) simply because browsers/annex-b cause divergence?

My take is that a parser should follow the spec strictly, and not concern itself with browser variances.

allenwb

allenwb commented on Aug 28, 2014

@allenwb

If you're building a browser (or processing web content scripts some other way) you need to implement Annex B in order to be compatible with existing web content. But, generally, stuff in Annex B is stuff a JS programmer should ever intentionally code. That's why it's in Annex B rather than the main body of the spec.

If you are building something other than a web browser and don't need to worry about compatibility will all existing web content, then you should just ignore Annex B and fully conform to the main body of the spec.

getify

getify commented on Aug 28, 2014

@getify

Building off what @allenwb said, I guess I would clarify my perspective as: a JS parser (not attached to a browser, mind-you) should take the more lenient (less errors) of either two positions if there's a divergence between the spec and browsers/annexB. If browsers throw an error but standard spec JS doesn't, the JS parser shouldn't. If the spec throws an error, but the browsers don't, the JS parser shouldn't. Only if both agree on throwing an error should the JS parser throw it. Just my 2 cents.

RReverser

RReverser commented on Sep 24, 2014

@RReverser
Member

Agree with @getify here. I think parser is more generic and can be used by any kind of tools, so should choose to throw less errors whenever it's allowed by spec.

marijnh

marijnh commented on Sep 24, 2014

@marijnh
Member

Agreed. Let's close this, and reconsider when it becomes clear what browsers will do in ES6-mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @marijnh@getify@allenwb@RReverser@r-e-d

        Issue actions

          Function statements in strict mode · Issue #118 · acornjs/acorn