Browse Source

scope fixes

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

12
src/Statement.js

@ -106,17 +106,7 @@ export default class Statement {
}
if ( isReference( node, parent ) ) {
// TODO this feels terribly kludgy. Function expression IDs and
// 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 );
const reference = new Reference( node, scope );
references.push( reference );
if ( node.type === 'Identifier' ) {

82
src/ast/attachScopes.js

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

Loading…
Cancel
Save