benjamn / ast-types

Esprima-compatible implementation of the Mozilla JS Parser API
MIT License
1.13k stars 195 forks source link

Missing catch binding breaks scope API #944

Open acutmore opened 11 months ago

acutmore commented 11 months ago

Using v0.16.1.

After parsing the following:

try {} catch { id; }

When walking the AST and then looking up the scope at id an exception is thrown:

 null does not match type Pattern
    at BaseType.assert (\node_modules\ast-types\lib\types.js:15:19)
    at addPattern (\node_modules\ast-types\lib\scope.js:256:28)
    at scanScope (\node_modules\ast-types\lib\scope.js:136:17)
    at Sp.scan (\node_modules\ast-types\lib\scope.js:109:13)
    at Sp.getBindings (\node_modules\ast-types\lib\scope.js:114:14)
    at Context.visitIdentifier (\ast.js:30:32)
    at Context.invokeVisitorMethod (\node_modules\ast-types\lib\path-visitor.js:283:51)
    at PVp.visitWithoutReset (\node_modules\ast-types\lib\path-visitor.js:158:32)
    at visitChildren (\node_modules\ast-types\lib\path-visitor.js:204:25)
    at PVp.visitWithoutReset (\node_modules\ast-types\lib\path-visitor.js:167:20)

Steps to reproduce:

const astTypes = require("ast-types");

const {builders: b, visit} = astTypes;

`try {} catch (e) { void x }`;

const main = b.file(b.program([
    // try {}
    b.tryStatement(b.blockStatement([]),
    // catch
       b.catchClause(
        /* param: */ null, // b.identifier("e"), // <- adding a catch binding avoids the bug
        /* guard: */ null,
        // {
        b.blockStatement([
            // void x
            b.expressionStatement(
                b.unaryExpression("void", b.identifier("x"))
            )
       ]))
    // }
    )
]));

visit(main, {
    visitIdentifier(path) {
        console.log(`at ${path.node.name}`); // 'at x'
        console.log(path.scope.getBindings()); // <- throws
        return false;
    }
});