@@ -83,8 +83,89 @@ function isRuleTesterConstruction (node) {
83
83
) ;
84
84
}
85
85
86
- module . exports = {
86
+ const INTERESTING_RULE_KEYS = new Set ( [ 'create' , 'meta' ] ) ;
87
87
88
+ /**
89
+ * Helper for `getRuleInfo`. Handles ESM rules.
90
+ */
91
+ function getRuleExportsESM ( ast ) {
92
+ return ast . body
93
+ . filter ( statement => statement . type === 'ExportDefaultDeclaration' )
94
+ . map ( statement => statement . declaration )
95
+ . reduce ( ( currentExports , node ) => {
96
+ if ( node . type === 'ObjectExpression' ) {
97
+ return node . properties . reduce ( ( parsedProps , prop ) => {
98
+ const keyValue = module . exports . getKeyName ( prop ) ;
99
+ if ( INTERESTING_RULE_KEYS . has ( keyValue ) ) {
100
+ parsedProps [ keyValue ] = prop . value ;
101
+ }
102
+ return parsedProps ;
103
+ } , { } ) ;
104
+ } else if ( isNormalFunctionExpression ( node ) ) {
105
+ return { create : node , meta : null , isNewStyle : false } ;
106
+ }
107
+ return currentExports ;
108
+ } , { } ) ;
109
+ }
110
+
111
+ /**
112
+ * Helper for `getRuleInfo`. Handles CJS rules.
113
+ */
114
+ function getRuleExportsCJS ( ast ) {
115
+ let exportsVarOverridden = false ;
116
+ let exportsIsFunction = false ;
117
+ return ast . body
118
+ . filter ( statement => statement . type === 'ExpressionStatement' )
119
+ . map ( statement => statement . expression )
120
+ . filter ( expression => expression . type === 'AssignmentExpression' )
121
+ . filter ( expression => expression . left . type === 'MemberExpression' )
122
+ . reduce ( ( currentExports , node ) => {
123
+ if (
124
+ node . left . object . type === 'Identifier' && node . left . object . name === 'module' &&
125
+ node . left . property . type === 'Identifier' && node . left . property . name === 'exports'
126
+ ) {
127
+ exportsVarOverridden = true ;
128
+ if ( isNormalFunctionExpression ( node . right ) ) {
129
+ // Check `module.exports = function () {}`
130
+
131
+ exportsIsFunction = true ;
132
+ return { create : node . right , meta : null , isNewStyle : false } ;
133
+ } else if ( node . right . type === 'ObjectExpression' ) {
134
+ // Check `module.exports = { create: function () {}, meta: {} }`
135
+
136
+ return node . right . properties . reduce ( ( parsedProps , prop ) => {
137
+ const keyValue = module . exports . getKeyName ( prop ) ;
138
+ if ( INTERESTING_RULE_KEYS . has ( keyValue ) ) {
139
+ parsedProps [ keyValue ] = prop . value ;
140
+ }
141
+ return parsedProps ;
142
+ } , { } ) ;
143
+ }
144
+ return { } ;
145
+ } else if (
146
+ ! exportsIsFunction &&
147
+ node . left . object . type === 'MemberExpression' &&
148
+ node . left . object . object . type === 'Identifier' && node . left . object . object . name === 'module' &&
149
+ node . left . object . property . type === 'Identifier' && node . left . object . property . name === 'exports' &&
150
+ node . left . property . type === 'Identifier' && INTERESTING_RULE_KEYS . has ( node . left . property . name )
151
+ ) {
152
+ // Check `module.exports.create = () => {}`
153
+
154
+ currentExports [ node . left . property . name ] = node . right ;
155
+ } else if (
156
+ ! exportsVarOverridden &&
157
+ node . left . object . type === 'Identifier' && node . left . object . name === 'exports' &&
158
+ node . left . property . type === 'Identifier' && INTERESTING_RULE_KEYS . has ( node . left . property . name )
159
+ ) {
160
+ // Check `exports.create = () => {}`
161
+
162
+ currentExports [ node . left . property . name ] = node . right ;
163
+ }
164
+ return currentExports ;
165
+ } , { } ) ;
166
+ }
167
+
168
+ module . exports = {
88
169
/**
89
170
* Performs static analysis on an AST to try to determine the final value of `module.exports`.
90
171
* @param {{ast: ASTNode, scopeManager?: ScopeManager} } sourceCode The object contains `Program` AST node, and optional `scopeManager`
@@ -94,61 +175,7 @@ module.exports = {
94
175
from the file, the return value will be `null`.
95
176
*/
96
177
getRuleInfo ( { ast, scopeManager } ) {
97
- const INTERESTING_KEYS = new Set ( [ 'create' , 'meta' ] ) ;
98
- let exportsVarOverridden = false ;
99
- let exportsIsFunction = false ;
100
-
101
- const exportNodes = ast . body
102
- . filter ( statement => statement . type === 'ExpressionStatement' )
103
- . map ( statement => statement . expression )
104
- . filter ( expression => expression . type === 'AssignmentExpression' )
105
- . filter ( expression => expression . left . type === 'MemberExpression' )
106
- . reduce ( ( currentExports , node ) => {
107
- if (
108
- node . left . object . type === 'Identifier' && node . left . object . name === 'module' &&
109
- node . left . property . type === 'Identifier' && node . left . property . name === 'exports'
110
- ) {
111
- exportsVarOverridden = true ;
112
-
113
- if ( isNormalFunctionExpression ( node . right ) ) {
114
- // Check `module.exports = function () {}`
115
-
116
- exportsIsFunction = true ;
117
- return { create : node . right , meta : null } ;
118
- } else if ( node . right . type === 'ObjectExpression' ) {
119
- // Check `module.exports = { create: function () {}, meta: {} }`
120
-
121
- exportsIsFunction = false ;
122
- return node . right . properties . reduce ( ( parsedProps , prop ) => {
123
- const keyValue = module . exports . getKeyName ( prop ) ;
124
- if ( INTERESTING_KEYS . has ( keyValue ) ) {
125
- parsedProps [ keyValue ] = prop . value ;
126
- }
127
- return parsedProps ;
128
- } , { } ) ;
129
- }
130
- return { } ;
131
- } else if (
132
- ! exportsIsFunction &&
133
- node . left . object . type === 'MemberExpression' &&
134
- node . left . object . object . type === 'Identifier' && node . left . object . object . name === 'module' &&
135
- node . left . object . property . type === 'Identifier' && node . left . object . property . name === 'exports' &&
136
- node . left . property . type === 'Identifier' && INTERESTING_KEYS . has ( node . left . property . name )
137
- ) {
138
- // Check `module.exports.create = () => {}`
139
-
140
- currentExports [ node . left . property . name ] = node . right ;
141
- } else if (
142
- ! exportsVarOverridden &&
143
- node . left . object . type === 'Identifier' && node . left . object . name === 'exports' &&
144
- node . left . property . type === 'Identifier' && INTERESTING_KEYS . has ( node . left . property . name )
145
- ) {
146
- // Check `exports.create = () => {}`
147
-
148
- currentExports [ node . left . property . name ] = node . right ;
149
- }
150
- return currentExports ;
151
- } , { } ) ;
178
+ const exportNodes = ast . sourceType === 'module' ? getRuleExportsESM ( ast ) : getRuleExportsCJS ( ast ) ;
152
179
153
180
const createExists = Object . prototype . hasOwnProperty . call ( exportNodes , 'create' ) ;
154
181
if ( ! createExists ) {
@@ -162,7 +189,7 @@ module.exports = {
162
189
return null ;
163
190
}
164
191
165
- return Object . assign ( { isNewStyle : ! exportsIsFunction , meta : null } , exportNodes ) ;
192
+ return Object . assign ( { isNewStyle : true , meta : null } , exportNodes ) ;
166
193
} ,
167
194
168
195
/**
0 commit comments