Browse Source

scope fixes

declarations-and-references
Rich-Harris 9 years ago
parent
commit
63f813edd7
  1. 12
      src/Statement.js
  2. 50
      src/ast/attachScopes.js

12
src/Statement.js

@ -106,17 +106,7 @@ export default class Statement {
} }
if ( isReference( node, parent ) ) { if ( isReference( node, parent ) ) {
// TODO this feels terribly kludgy. Function expression IDs and const reference = new Reference( node, scope );
// function parameters will show up in the parent scope – this
// hack fixes that
let realScope = scope;
if ( /Function/.test( parent.type ) ) {
if ( parent.type !== 'FunctionDeclaration' || node !== parent.id ) {
realScope = parent.body._scope;
}
}
const reference = new Reference( node, realScope );
references.push( reference ); references.push( reference );
if ( node.type === 'Identifier' ) { if ( node.type === 'Identifier' ) {

50
src/ast/attachScopes.js

@ -13,52 +13,52 @@ export default function attachScopes ( statement ) {
enter ( node, parent ) { enter ( node, parent ) {
let newScope; let newScope;
switch ( node.type ) { // function foo () {...}
case 'FunctionDeclaration': // class Foo {...}
if ( /(Function|Class)Declaration/.test( node.type ) ) {
scope.addDeclaration( node, false, false ); scope.addDeclaration( node, false, false );
break; }
// var foo = 1
// TODO can we have multiple declarations at this point? when
// do we create synthetic var nodes?
if ( node.type === 'VariableDeclaration' ) {
const isBlockDeclaration = blockDeclarations[ node.kind ];
node.declarations.forEach( declarator => {
scope.addDeclaration( declarator, isBlockDeclaration, true );
});
}
case 'BlockStatement': // create new function scope
if ( parent && /Function/.test( parent.type ) ) { if ( /Function/.test( node.type ) ) {
newScope = new Scope({ newScope = new Scope({
parent: scope, parent: scope,
block: false, block: false,
params: parent.params params: node.params
}); });
// named function expressions - the name is considered // named function expressions - the name is considered
// part of the function's scope // part of the function's scope
if ( parent.type === 'FunctionExpression' && parent.id ) { if ( node.type === 'FunctionExpression' && node.id ) {
newScope.addDeclaration( parent, false, false ); newScope.addDeclaration( node, false, false );
} }
} else { }
// create new block scope
if ( node.type === 'BlockStatement' && !/Function/.test( parent.type ) ) {
newScope = new Scope({ newScope = new Scope({
parent: scope, parent: scope,
block: true block: true
}); });
} }
break; // catch clause has its own block scope
if ( node.type === 'CatchClause' ) {
case 'CatchClause':
newScope = new Scope({ newScope = new Scope({
parent: scope, parent: scope,
params: [ node.param ], params: [ node.param ],
block: true block: true
}); });
break;
case 'VariableDeclaration':
node.declarations.forEach( declarator => {
const isBlockDeclaration = node.type === 'VariableDeclaration' && blockDeclarations[ node.kind ];
scope.addDeclaration( declarator, isBlockDeclaration, true );
});
break;
case 'ClassDeclaration':
scope.addDeclaration( node, false, false );
break;
} }
if ( newScope ) { if ( newScope ) {

Loading…
Cancel
Save