Skip to content
This repository has been archived by the owner on Aug 15, 2024. It is now read-only.

Fix: wrong resolution about default parameters #33

Merged
merged 2 commits into from
Nov 21, 2017

Conversation

mysticatea
Copy link
Member

Fixes eslint/eslint#9335.

This PR fixes wrong resolutions about the references in default parameters. In the following case:

let a // (A)
function f(x = a) { // This `a` should be resolved to (A), but was resovled to (B).
    let a // (B)
}

After this PR, the a in default parameters is resolved to (A) correctly.


This fixing is not ideal.

As the step 27.a of 9.2.12 FunctionDeclarationInstantiation( func, argumentsList ) mentioned, it should make new scope for the function body if the parameters has any default value. However, I guessed that it's a huge breaking change which breaks many ESLint rules. So I kept scope structure and modified the resolution logic.

@mysticatea mysticatea added the bug label Oct 28, 2017
@ilyavolodin
Copy link
Member

@mysticatea Can you explain a bit more about that new scope? functions already create their own scope, would that be another extra scope on top of that? Why is that necessary?

@mysticatea
Copy link
Member Author

mysticatea commented Nov 1, 2017

@ilyavolodin That new scope separates the variables in the body from default parameters. For example:

let x = 1
function foo(a = x, b = y) {
    let x = 1, y = 2
}
// Scopes
{
    type: "global",
    variables: ["x", "foo"],
    references: [],
    childScopes: [
        {
            type: "function",
            variables: ["arguments", "a", "b"],
            references: ["x", "y"], // This `x` comes from the global scope. This `y` is not defined.
            childScopes: [
                //
                // Ideally, requires this function-body scope only if the function has default parameters.
                // This scope separates the variables in the body from default parameters.
                //
                // EDIT: This `function-body`scope has the variables which are copied from `function` scope.
                //       Those copied variables prevent redeclarations of parameters.
                //       `No-shadow` rule should not report the copied variables.
                //
                {
                    type: "functionBody",
                    variables: ["arguments", "a", "b", "x", "y"],
                    references: [],
                    childScopes: [],
                },
            ],
        },
    ],
}

If the function-body scope does not exist:

// Scopes
{
    type: "global",
    variables: ["x", "foo"],
    references: [],
    childScopes: [
        {
            type: "function",
            variables: ["arguments", "a", "b", "x", "y"],
            references: ["x", "y"], // These `x` and `y` comes from this scope because it's defined.
            childScopes: [],
        },
    ],
}

@ilyavolodin
Copy link
Member

Thanks for the explanation! I see how this might result in a lot of breaking changes. Could we do it in the next major version? I'd prefer to create scopes as appropriate based on the specifications. We can merge this in now, but create another issue to introduce extra scope for the default parameters in the next major version of ESLint.

@mysticatea
Copy link
Member Author

Could we do it in the next major version?

Sure. I can.

@ilyavolodin
Copy link
Member

Do you think we should merge this in now, and do a correct fix in the next major version of ESLint? Keep in mind, we are probably about half-a-year away from the next major release.

@mysticatea
Copy link
Member Author

I'm happy if this is merged and I make the breaking change when the next major release.

As a side note, I'd like to make one more change in the next major release: removing TDZ scope. Though all core rules ignore the TDZ scopes, I think it's out of specification. TDZ is timing matter rather than scope structure.

@mysticatea mysticatea merged commit 982a71f into master Nov 21, 2017
@mysticatea mysticatea deleted the fix-default-parameters branch November 21, 2017 06:55
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

no-use-before-define false positive
2 participants