@@ -19,6 +19,11 @@ var util = require('ast-util');
19
19
*/
20
20
function ArrowFunctionExpressionVisitor ( ) {
21
21
PathVisitor . call ( this ) ;
22
+
23
+ // In order to optimize the visitor we use a specific one for parsing the
24
+ // the body of the arrow function. This way very common types like Identifier
25
+ // are only visited under the subtree we're interested in.
26
+ this . bodyVisitor = new BodyVisitor ( this ) ;
22
27
}
23
28
ArrowFunctionExpressionVisitor . prototype = Object . create ( PathVisitor . prototype ) ;
24
29
ArrowFunctionExpressionVisitor . prototype . constructor = ArrowFunctionExpressionVisitor ;
@@ -30,7 +35,8 @@ ArrowFunctionExpressionVisitor.prototype.constructor = ArrowFunctionExpressionVi
30
35
* @return {?Node }
31
36
*/
32
37
ArrowFunctionExpressionVisitor . prototype . visitArrowFunctionExpression = function ( path ) {
33
- this . traverse ( path ) ;
38
+ // Descend into the body using a specific visitor
39
+ this . traverse ( path , this . bodyVisitor ) ;
34
40
35
41
var node = path . node ;
36
42
var hasThisExpression = ThisExpressionVisitor . hasThisExpression ( node ) ;
@@ -53,13 +59,29 @@ ArrowFunctionExpressionVisitor.prototype.visitArrowFunctionExpression = function
53
59
}
54
60
} ;
55
61
62
+ /**
63
+ * Visits the body of an arrow function expressions.
64
+ *
65
+ * @constructor
66
+ * @private
67
+ * @extends PathVisitor
68
+ */
69
+ function BodyVisitor ( parent ) {
70
+ // Support nested arrow function expressions by delegating on the parent visitor
71
+ this . visitArrowFunctionExpression = parent . visitArrowFunctionExpression ;
72
+
73
+ PathVisitor . call ( this ) ;
74
+ }
75
+ BodyVisitor . prototype = Object . create ( PathVisitor . prototype ) ;
76
+ BodyVisitor . prototype . constructor = BodyVisitor ;
77
+
56
78
/**
57
79
* Ensures that `arguments` directly contained in arrow functions is hoisted.
58
80
*
59
81
* @param {types.NodePath } path
60
82
* @return {?Node }
61
83
*/
62
- ArrowFunctionExpressionVisitor . prototype . visitIdentifier = function ( path ) {
84
+ BodyVisitor . prototype . visitIdentifier = function ( path ) {
63
85
var node = path . node ;
64
86
65
87
if ( node . name === 'arguments' && util . isReference ( path ) ) {
@@ -69,15 +91,15 @@ ArrowFunctionExpressionVisitor.prototype.visitIdentifier = function(path) {
69
91
}
70
92
}
71
93
72
- this . traverse ( path ) ;
94
+ return false ; // nothing else to look at here
73
95
} ;
74
96
75
97
/**
76
98
* @private
77
99
* @param {types.NodePath } path
78
100
* @return {?types.Scope } The nearest non-arrow function scope above `path`.
79
101
*/
80
- ArrowFunctionExpressionVisitor . prototype . associatedFunctionScope = function ( path ) {
102
+ BodyVisitor . prototype . associatedFunctionScope = function ( path ) {
81
103
var scope = path . scope ;
82
104
while ( scope && n . ArrowFunctionExpression . check ( scope . path . node ) ) {
83
105
scope = scope . parent ;
0 commit comments