Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Normative: Allow duplicate FunctionDeclarations in a block
Browse files Browse the repository at this point in the history
A previously overlooked aspect of intersection semantics for
 #sec-block-level-function-declarations-web-legacy-compatibility-semantics
is the ability to have multiple function declarations with the same name
in the same block. This patch relaxes that constraint in sloppy mode.
Because it relaxes a static semantics rule, and replaces rather than
simply adds behavior, it is in the main spec text rather than Annex B.
The patch also puts the non-normative text in Annex B in an emu-note.

Fixes #320.
littledan committed Mar 4, 2016
1 parent e75390d commit d6afdd1
Showing 1 changed file with 65 additions and 59 deletions.
124 changes: 65 additions & 59 deletions spec.html
Original file line number Diff line number Diff line change
@@ -14153,7 +14153,7 @@ <h1>Static Semantics: Early Errors</h1>
<emu-grammar>Block : `{` StatementList `}`</emu-grammar>
<ul>
<li>
It is a Syntax Error if the LexicallyDeclaredNames of |StatementList| contains any duplicate entries.
It is a Syntax Error if the LexicallyDeclaredNames of |StatementList| contains any duplicate entries, unless the source code matching this production is not strict mode code and the duplicate entries are only bound by FunctionDeclarations.
</li>
<li>
It is a Syntax Error if any element of the LexicallyDeclaredNames of |StatementList| also occurs in the VarDeclaredNames of |StatementList|.
@@ -14476,7 +14476,11 @@ <h1>Runtime Semantics: BlockDeclarationInstantiation( _code_, _env_ )</h1>
1. If _d_ is a |GeneratorDeclaration| production or a |FunctionDeclaration| production, then
1. Let _fn_ be the sole element of the BoundNames of _d_.
1. Let _fo_ be the result of performing InstantiateFunctionObject for _d_ with argument _env_.
1. Perform _envRec_.InitializeBinding(_fn_, _fo_).
1. If _envRec_.HasBinding(_fn_) is *true*, then
1. Assert: _d_ is a |FunctionDeclaration|.
1. _envRec_.SetMutableBinding(_fn_, _fo_, *false*).
1. Else,
1. Perform _envRec_.InitializeBinding(_fn_, _fo_).
</emu-alg>
</emu-clause>
</emu-clause>
@@ -36555,63 +36559,65 @@ <h1>Labelled Function Declarations</h1>
<!-- es6num="B.3.3" -->
<emu-annex id="sec-block-level-function-declarations-web-legacy-compatibility-semantics">
<h1>Block-Level Function Declarations Web Legacy Compatibility Semantics</h1>
<p>Prior to ECMAScript 2015, the ECMAScript specification did not define the occurrence of a |FunctionDeclaration| as an element of a |Block| statement's |StatementList|. However, support for that form of |FunctionDeclaration| was an allowable extension and most browser-hosted ECMAScript implementations permitted them. Unfortunately, the semantics of such declarations differ among those implementations. Because of these semantic differences, existing web ECMAScript code that uses |Block| level function declarations is only portable among browser implementation if the usage only depends upon the semantic intersection of all of the browser implementations for such declarations. The following are the use cases that fall within that intersection semantics:</p>
<ol>
<li>
<p>A function is declared and only referenced within a single block</p>
<ul>
<li>
A |FunctionDeclaration| whose |BindingIdentifier| is the name _f_ occurs exactly once within the function code of an enclosing function _g_ and that declaration is nested within a |Block|.
</li>
<li>
No other declaration of _f_ that is not a `var` declaration occurs within the function code of _g_
</li>
<li>
All occurrences of _f_ as an |IdentifierReference| are within the |StatementList| of the |Block| containing the declaration of _f_.
</li>
</ul>
</li>
<li>
<p>A function is declared and possibly used within a single |Block| but also referenced by an inner function definition that is not contained within that same |Block|.</p>
<ul>
<li>
A |FunctionDeclaration| whose |BindingIdentifier| is the name _f_ occurs exactly once within the function code of an enclosing function _g_ and that declaration is nested within a |Block|.
</li>
<li>
No other declaration of _f_ that is not a `var` declaration occurs within the function code of _g_
</li>
<li>
There may be occurrences of _f_ as an |IdentifierReference| within the |StatementList| of the |Block| containing the declaration of _f_.
</li>
<li>
There is at least one occurrence of _f_ as an |IdentifierReference| within another function _h_ that is nested within _g_ and no other declaration of _f_ shadows the references to _f_ from within _h_.
</li>
<li>
All invocations of _h_ occur after the declaration of _f_ has been evaluated.
</li>
</ul>
</li>
<li>
<p>A function is declared and possibly used within a single block but also referenced within subsequent blocks.</p>
<ul>
<li>
A |FunctionDeclaration| whose |BindingIdentifier| is the name _f_ occurs exactly once within the function code of an enclosing function _g_ and that declaration is nested within a |Block|.
</li>
<li>
No other declaration of _f_ that is not a `var` declaration occurs within the function code of _g_
</li>
<li>
There may be occurrences of _f_ as an |IdentifierReference| within the |StatementList| of the |Block| containing the declaration of _f_.
</li>
<li>
There is at least one occurrence of _f_ as an |IdentifierReference| within the function code of _g_ that lexically follows the |Block| containing the declaration of _f_.
</li>
</ul>
</li>
</ol>
<p>The first use case is interoperable with the semantics of |Block| level function declarations provided by ECMAScript 2015. Any pre-existing ECMAScript code that employs that use case will operate using the Block level function declarations semantics defined by clauses 9, 13, and 14 of this specification.</p>
<p>ECMAScript 2015 interoperability for the second and third use cases requires the following extensions to the clause <emu-xref href="#sec-ordinary-and-exotic-objects-behaviours"></emu-xref>, clause <emu-xref href="#sec-ecmascript-language-functions-and-classes"></emu-xref>, clause <emu-xref href="#sec-eval-x"></emu-xref> and clause <emu-xref href="#sec-globaldeclarationinstantiation"></emu-xref> semantics.</p>
<p>If an ECMAScript implementation has a mechanism for reporting diagnostic warning messages, a warning should be produced when code contains a |FunctionDeclaration| for which these compatibility semantics are applied and introduce observable differences from non-compatibility semantics. For example, if a var binding is not introduced because its introduction would create an early error, a warning message should not be produced.</p>
<emu-note>
<p>Prior to ECMAScript 2015, the ECMAScript specification did not define the occurrence of a |FunctionDeclaration| as an element of a |Block| statement's |StatementList|. However, support for that form of |FunctionDeclaration| was an allowable extension and most browser-hosted ECMAScript implementations permitted them. Unfortunately, the semantics of such declarations differ among those implementations. Because of these semantic differences, existing web ECMAScript code that uses |Block| level function declarations is only portable among browser implementation if the usage only depends upon the semantic intersection of all of the browser implementations for such declarations. The following are the use cases that fall within that intersection semantics:</p>
<ol>
<li>
<p>A function is declared and only referenced within a single block</p>
<ul>
<li>
One or more |FunctionDeclaration|s whose |BindingIdentifier| is the name _f_ occur within the function code of an enclosing function _g_ and that declaration is nested within a |Block|.
</li>
<li>
No other declaration of _f_ that is not a `var` declaration occurs within the function code of _g_
</li>
<li>
All occurrences of _f_ as an |IdentifierReference| are within the |StatementList| of the |Block| containing the declaration of _f_.
</li>
</ul>
</li>
<li>
<p>A function is declared and possibly used within a single |Block| but also referenced by an inner function definition that is not contained within that same |Block|.</p>
<ul>
<li>
One or more |FunctionDeclaration|s whose |BindingIdentifier| is the name _f_ occur within the function code of an enclosing function _g_ and that declaration is nested within a |Block|.
</li>
<li>
No other declaration of _f_ that is not a `var` declaration occurs within the function code of _g_
</li>
<li>
There may be occurrences of _f_ as an |IdentifierReference| within the |StatementList| of the |Block| containing the declaration of _f_.
</li>
<li>
There is at least one occurrence of _f_ as an |IdentifierReference| within another function _h_ that is nested within _g_ and no other declaration of _f_ shadows the references to _f_ from within _h_.
</li>
<li>
All invocations of _h_ occur after the declaration of _f_ has been evaluated.
</li>
</ul>
</li>
<li>
<p>A function is declared and possibly used within a single block but also referenced within subsequent blocks.</p>
<ul>
<li>
One or more |FunctionDeclaration| whose |BindingIdentifier| is the name _f_ occur within the function code of an enclosing function _g_ and that declaration is nested within a |Block|.
</li>
<li>
No other declaration of _f_ that is not a `var` declaration occurs within the function code of _g_
</li>
<li>
There may be occurrences of _f_ as an |IdentifierReference| within the |StatementList| of the |Block| containing the declaration of _f_.
</li>
<li>
There is at least one occurrence of _f_ as an |IdentifierReference| within the function code of _g_ that lexically follows the |Block| containing the declaration of _f_.
</li>
</ul>
</li>
</ol>
<p>The first use case is interoperable with the semantics of |Block| level function declarations provided by ECMAScript 2015. Any pre-existing ECMAScript code that employs that use case will operate using the Block level function declarations semantics defined by clauses 9, 13, and 14 of this specification.</p>
<p>ECMAScript 2015 interoperability for the second and third use cases requires the following extensions to the clause <emu-xref href="#sec-ordinary-and-exotic-objects-behaviours"></emu-xref>, clause <emu-xref href="#sec-ecmascript-language-functions-and-classes"></emu-xref>, clause <emu-xref href="#sec-eval-x"></emu-xref> and clause <emu-xref href="#sec-globaldeclarationinstantiation"></emu-xref> semantics.</p>
<p>If an ECMAScript implementation has a mechanism for reporting diagnostic warning messages, a warning should be produced when code contains a |FunctionDeclaration| for which these compatibility semantics are applied and introduce observable differences from non-compatibility semantics. For example, if a var binding is not introduced because its introduction would create an early error, a warning message should not be produced.</p>
</emu-note>
<emu-annex id="sec-web-compat-functiondeclarationinstantiation">
<h1>Changes to FunctionDeclarationInstantiation</h1>
<p>During FunctionDeclarationInstantiation the following steps are performed in place of step 29:</p>

0 comments on commit d6afdd1

Please sign in to comment.