Incorrect restriction on BindingIdentifier of FunctionDeclaration

NEW
Unassigned

Status

()

Core
JavaScript Engine
3 years ago
3 years ago

People

(Reporter: jugglinmike, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

3 years ago
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.
(Reporter)

Comment 2

3 years ago
> 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)
(Reporter)

Comment 4

3 years ago
A spec bug has been filed: https://bugs.ecmascript.org/show_bug.cgi?id=4243
(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".
You need to log in before you can comment on or make changes to this bug.