ecma262 icon indicating copy to clipboard operation
ecma262 copied to clipboard

B.3.2.1 - Which `FunctionDeclaration` parse nodes list does it iterate?

Open nicolo-ribaudo opened this issue 3 years ago • 6 comments

Description:

We are trying to fix the handling of function declarations in blocks in Babel (https://github.com/babel/babel/pull/14203), and I don't understand what the spec does.

At step 29.a of B.3.2.1, it says:

a. For each FunctionDeclaration f that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause, do

However, usually "For each" iterates the elements of a list. Is it iterating over the functions (deeply) contained within the function that is currently being instantiated? Or is it something like "If the current FunctionDeclarationInstantiation call has been caused by evaluating a FunctionDeclaration parse node, let f be that parse node"?

nicolo-ribaudo avatar Feb 13 '22 15:02 nicolo-ribaudo

I agree that it's odd: the criterion "each FunctionDeclarationthat is directly contained in the StatementList of a Block, CaseClause, or DefaultClause" makes it sound like we need to look at any Block, CaseClause, or DefaultClause, anywhere in the Script.

In ES6, that step is:

For each FunctionDeclaration f in varDeclarations that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause,

(emphasis mine), which makes it clear you don't have to go looking everywhere. But the phrase "in varDeclarations" was removed in efbfc88a to resolve https://tc39.es/archives/bugzilla/4427/, which links back to an issue that @bakkot raised in 2015.

However, it looks like the change that @allenwb suggested in 4427 wasn't applied correctly: in addition to dropping "in varDeclarations", he also appended "Contained within code" (where code is the FunctionBody of the function that FunctionDeclarationInstantiation is being called on), but that wasn't added.

jmdyck avatar Feb 13 '22 21:02 jmdyck

That might still be somewhat problematic because when instantiating f in

function f() {
  function g() {
    { function h() {} }
  }
}

we don't want to look at h.

nicolo-ribaudo avatar Feb 13 '22 21:02 nicolo-ribaudo

In the phrase "Contained within code", I suspect the capital 'C' alludes to the 'Contains' SDO, which avoids looking inside nested functionDecls.

(To make it a proper invocation of 'Contains', I think it would need to be something like "... any Block, CaseClause, or DefaultClause x such that code Contains x".)

jmdyck avatar Feb 13 '22 21:02 jmdyck

I read "directly" as specifying that h (indirectly contained) is not considered.

bathos avatar Feb 14 '22 03:02 bathos

@bathos In my example the function is directly contained in a block. I'll open a PR with "Contains".

nicolo-ribaudo avatar Feb 14 '22 09:02 nicolo-ribaudo

Ah, got it — “directly contained” only describes the declaration relative to the block, not the block relative to the “root” statement list.

bathos avatar Feb 14 '22 11:02 bathos