Open Bug 1145191 Opened 9 years ago Updated 2 years ago

Incorrect restriction on BindingIdentifier of FunctionDeclaration

Categories

(Core :: JavaScript Engine, defect)

x86_64
Linux
defect

Tracking

()

People

(Reporter: jugglinmike, Unassigned)

Details

The BindingIdentifier of FunctionDeclarations is incorrectly interpreted
according to the strictness of the declared function (and not according to the
strictness of the code in which it was declared):

    js> function static() {}
    js> function static() { 'use strict'; }
    typein:23:32 SyntaxError: redefining static is deprecated:
    typein:23:32 function static() { 'use strict'; }
    typein:23:32 ................................^

Expected: no eror is thrown for either statement.
Actual: an error is thrown when the body of the declared function opts in to
strict mode
gecko-dev revision: f8581d6c769a9d48ed7057b5d298a98178cc5f26 (Thu Mar 19 14:00:57 2015 +0100)

From the ES5 spec:

> The following tokens are also considered to be FutureReservedWords when they
> occur within strict mode code (see 10.1.1). [1]

...which defines "strict mode code":

> Function code that is part of a FunctionDeclaration, FunctionExpression, or
> accessor PropertyAssignment is strict function code if its
> FunctionDeclaration, FunctionExpression, or PropertyAssignment is contained
> in strict mode code or if the function code begins with a Directive Prologue
> that contains a Use Strict Directive. [2]

...and "function code":

> Function code is source text that is parsed as part of a FunctionBody. The
> function code of a particular FunctionBody does not include any source text
> that is parsed as part of a nested FunctionBody. Function code also denotes
> the source text supplied when using the built-in Function object as a
> constructor. More precisely, the last parameter provided to the Function
> constructor is converted to a String and treated as the FunctionBody. If more
> than one parameter is provided to the Function constructor, all parameters
> except the last one are converted to Strings and concatenated together,
> separated by commas. The resulting String is interpreted as the
> FormalParameterList for the FunctionBody defined by the last parameter. The
> function code for a particular instantiation of a Function does not include
> any source text that is parsed as part of a nested FunctionBody. [3]

So since the BindingIdentifier is not considered part of the function code, it
should not be interpreted according to the strictness of the function itself.
This interpretation also holds in ECMAScript 6 [4].

[1] http://es5.github.io/#x11
[2] http://es5.github.io/#x10.1.1
[3] http://es5.github.io/#function-code
[4] Relevant definitions in the ES6 spec draft:
    - https://people.mozilla.org/~jorendorff/es6-draft.html#sec-identifiers-static-semantics-early-errors
    - https://people.mozilla.org/~jorendorff/es6-draft.html#sec-strict-mode-code
    - https://people.mozilla.org/~jorendorff/es6-draft.html#sec-types-of-source-code
    - https://people.mozilla.org/~jorendorff/es6-draft.html#sec-function-definitions
I think this is actually a spec bug, otherwise it's always possible to name a FunctionDeclaration with a strict-mode reserved word. For example this script:
---
"use strict";
function static {}
---

1) The global code (ES6, 10.2) does not include the FunctionDeclaration.
2) The function code (ES6, 10.2) does not include the BindingIdentifier.

That would mean the BindingIdentifier lives in no-man's-land without any rules. This is certainly not intended.
> 1) The global code (ES6, 10.2) does not include the FunctionDeclaration.

As I read it, that section doesn't state that FunctionDeclarations are not part of the surrounding global code--only their "source text" seems to be excluded:

> The global code of a particular Script does not include any source text that
> is parsed as part of a FunctionDeclaration, FunctionExpression,
> GeneratorDeclaration, GeneratorExpression, MethodDefinition, ArrowFunction,
> ClassDeclaration, or ClassExpression.
This restriction makes sense to me. I agree with André that if this is not allowed by the spec, we should change that instead. (Chrome doesn't allow it either)
(In reply to André Bargull from comment #1)
> I think this is actually a spec bug, otherwise it's always possible to name
> a FunctionDeclaration with a strict-mode reserved word. For example this
> script:
> ---
> "use strict";
> function static {}
> ---
> 
> 1) The global code (ES6, 10.2) does not include the FunctionDeclaration.
> 2) The function code (ES6, 10.2) does not include the BindingIdentifier.
> 
> That would mean the BindingIdentifier lives in no-man's-land without any
> rules. This is certainly not intended.

This is defined in the grammar and has a explicit early error definition: 



14.1 Function Definitions

  FunctionDeclaration[Yield, Default] :
    function BindingIdentifier[?Yield] ( FormalParameters ) { FunctionBody }



12.1

  BindingIdentifier[Yield] :
    Identifier
    [~Yield] yield  



12.1.1
  
  Identifier : IdentifierName but not ReservedWord


    It is a Syntax Error if this phrase is contained in strict mode code and the StringValue of IdentifierName is: "implements", "interface", "let", "package", "private", "protected", "public", "static", or "yield".
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.