@@ -27,7 +27,7 @@ function declToAssign(decl: t.VariableDeclarator): t.AssignmentExpression | null
2727
2828function getFunctionArgs ( path : NodePath < t . Node > ) : string [ ] {
2929 const node = path . node ;
30- if ( node . type === 'FunctionDeclaration' ||
30+ if ( node . type === 'FunctionDeclaration' ||
3131 node . type === 'FunctionExpression' ) {
3232 return ( < any > node ) . params . map ( ( x : t . Identifier ) => x . name ) ;
3333 }
@@ -37,7 +37,7 @@ function getFunctionArgs(path: NodePath<t.Node>): string[] {
3737}
3838
3939function getBlock ( node : t . Node ) : t . Statement [ ] {
40- if ( node . type === 'FunctionDeclaration' ||
40+ if ( node . type === 'FunctionDeclaration' ||
4141 node . type === 'FunctionExpression' ) {
4242 return ( < t . FunctionDeclaration > node ) . body . body ;
4343 }
@@ -49,7 +49,36 @@ function getBlock(node: t.Node): t.Statement[] {
4949 }
5050}
5151
52+ const func = {
53+ enter ( path : NodePath < t . FunctionDeclaration | t . FunctionExpression > ) {
54+ ( < any > path . node ) . toDecl = [ ]
55+ } ,
56+ exit ( path : NodePath < t . FunctionDeclaration | t . FunctionExpression > ) {
57+ const toDecl : t . Identifier [ ] | undefined = ( < any > path . node ) . toDecl
58+ if ( toDecl && toDecl . length > 0 ) {
59+ path . node . body . body . unshift ( t . variableDeclaration ( 'var' ,
60+ lifted ( toDecl . map ( d => t . variableDeclarator ( d ) ) ) ) )
61+ }
62+ }
63+ }
64+
65+ const prog = {
66+ enter ( path : NodePath < t . Program > ) {
67+ ( < any > path . node ) . toDecl = [ ]
68+ } ,
69+ exit ( path : NodePath < t . Program > ) {
70+ const toDecl : t . Identifier [ ] | undefined = ( < any > path . node ) . toDecl
71+ if ( toDecl && toDecl . length > 0 ) {
72+ path . node . body . unshift ( t . variableDeclaration ( 'var' ,
73+ lifted ( toDecl . map ( d => t . variableDeclarator ( d ) ) ) ) )
74+ }
75+ }
76+ }
77+
5278const lift : Visitor = {
79+ Program : prog ,
80+ FunctionDeclaration : func ,
81+ FunctionExpression : func ,
5382 VariableDeclaration ( path : NodePath < Lifted < t . VariableDeclaration > > ) {
5483 if ( path . node . lifted ) {
5584 return ;
@@ -73,9 +102,22 @@ const lift: Visitor = {
73102 throw new Error ( `Destructuring assignment not supported` ) ;
74103 }
75104 const id = decl . id . name ;
76- const newDecl = t . variableDeclaration ( kind ,
77- [ t . variableDeclarator ( decl . id ) ] ) ;
78- getBlock ( topScope . node ) . unshift ( lifted ( newDecl ) ) ;
105+ // This checks for the following case:
106+ //
107+ // function(x) { var x = 10; }
108+ //
109+ // is the same as:
110+ //
111+ // function(x) { x = 10; }
112+ //
113+ // Therefore, we do not need to lift x. Instead, we eliminate the
114+ // declaration and only turn it into an assignment.
115+ if ( ( kind === 'var' && topArgs . includes ( id ) ) === false ) {
116+ ( < any > topScope . node ) . toDecl . push ( decl . id )
117+ //const newDecl = t.variableDeclaration(kind,
118+ //[t.variableDeclarator(decl.id)]);
119+ //getBlock(topScope.node).unshift(lifted(newDecl));
120+ }
79121 if ( decl . init !== null ) {
80122 // If we call path.insertAfter here, we will add assignments in reverse
81123 // order. Fortunately, path.insertAfter can take an array of nodes.
0 commit comments