1
1
'use strict' ;
2
2
3
+ const USE_JESSIE_BEFORE_FIRST_STATEMENT_REGEXP = / ^ \s * \/ \/ \s * @ j e s s i e - c h e c k \s * $ / m;
4
+ const USE_JESSIE_FIRST_STATEMENT_REGEXP = / ^ ( ' u s e \s + j e s s i e ' | " u s e \s + j e s s i e " | i m p o r t \s + ( ' @ j e s s i e .j s \/ t r a n s f o r m - t h i s - m o d u l e ' | " j e s s i e .j s \/ t r a n s f o r m - t h i s - m o d u l e " ) ) / ;
5
+
3
6
// This is all one line so that we don't mess up
4
7
// eslint's error locations.
5
8
//
@@ -9,80 +12,90 @@ const jessieRulesOneLine = `\
9
12
curly: ['error', 'all']\
10
13
,eqeqeq: ['error', 'always']\
11
14
,no-bitwise: ['error']\
12
- ,no-fallthrough: ['error', { commentPattern: 'fallthrough is not allowed' }]\
13
- ,no-plusplus: ['error']\
15
+ ,no-fallthrough: ['error', { commentPattern: 'fallthrough is not allowed in Jessie' }]\
14
16
,no-restricted-globals: ['error', 'RegExp', 'Date']\
15
17
,no-restricted-syntax: ['error', \
16
18
{\
17
19
selector: "BinaryExpression[operator='in']",\
18
- message: "'in' is not allowed.",\
20
+ message: "'in' is not allowed in Jessie",\
21
+ },\
22
+ {\
23
+ selector: "UpdateExpression[operator='++'][prefix=false]",\
24
+ message: "postfix '++' is not allowed in Jessie",\
25
+ },\
26
+ {\
27
+ selector: "UpdateExpression[operator='--'][prefix=false]",\
28
+ message: "postfix '--' is not allowed in Jessie",\
19
29
},\
20
30
{\
21
31
selector: "BinaryExpression[operator='instanceof']",\
22
- message: "'instanceof' is not allowed. ",\
32
+ message: "'instanceof' is not allowed in Jessie ",\
23
33
},\
24
34
{\
25
35
selector: 'NewExpression',\
26
- message: "'new' is not allowed. ",\
36
+ message: "'new' is not allowed in Jessie ",\
27
37
},\
28
38
{\
29
39
selector: 'FunctionDeclaration[generator=true]',\
30
- message: 'generators are not allowed. ',\
40
+ message: 'generators are not allowed in Jessie ',\
31
41
},\
32
42
{\
33
43
selector: 'FunctionDeclaration[async=true]',\
34
- message: 'async functions are not allowed. ',\
44
+ message: 'async functions are not allowed in Jessie ',\
35
45
},\
36
46
{\
37
47
selector: 'FunctionExpression[async=true]',\
38
- message: 'async functions are not allowed. ',\
48
+ message: 'async functions are not allowed in Jessie ',\
39
49
},\
40
50
{\
41
51
selector: 'ArrowFunctionExpression[async=true]',\
42
- message: 'async functions are not allowed. ',\
52
+ message: 'async functions are not allowed in Jessie ',\
43
53
},\
44
54
{\
45
55
selector: 'DoWhileStatement',\
46
- message: 'do/while statements are not allowed. ',\
56
+ message: 'do/while statements are not allowed in Jessie ',\
47
57
},\
48
58
{\
49
59
selector: 'ThisExpression',\
50
- message: "'this' not allowed. ",\
60
+ message: "'this' not allowed in Jessie ",\
51
61
},\
52
62
{\
53
63
selector: "UnaryExpression[operator='delete']",\
54
- message: "'delete' not allowed. ",\
64
+ message: "'delete' not allowed in Jessie ",\
55
65
},\
56
66
{\
57
67
selector: 'ForInStatement',\
58
- message: 'for/in statements are not allowed; use for/of Object.keys(val).',\
68
+ message: 'for/in statements are not allowed in Jessie; use for/of Object.keys(val).',\
69
+ },\
70
+ {\
71
+ selector: 'MemberExpression[computed=true][property.type!="Literal"][property.type!="UnaryExpression"]',\
72
+ message: "computed property names are not allowed in Jessie (except with leading '+')",\
59
73
},\
60
74
{\
61
- selector: 'MemberExpression[computed=true]',\
62
- message: 'computed property names are not allowed. ',\
75
+ selector: 'MemberExpression[computed=true][property.type="UnaryExpression"][property.operator!="+"] ',\
76
+ message: 'computed property names are not allowed in Jessie (except with leading '+') ',\
63
77
},\
64
78
{\
65
79
selector: 'Super',\
66
- message: "'super' is not allowed. ",\
80
+ message: "'super' is not allowed in Jessie ",\
67
81
},\
68
82
{\
69
83
selector: 'MetaProperty',\
70
- message: "'MetaProperty' is not allowed. ",\
84
+ message: "'MetaProperty' is not allowed in Jessie ",\
71
85
},\
72
86
{\
73
87
selector: 'ClassExpression',\
74
- message: "'ClassExpression' is not allowed. ",\
88
+ message: "'ClassExpression' is not allowed in Jessie ",\
75
89
},\
76
90
{\
77
91
selector: "CallExpression[callee.name='eval']",\
78
- message: "'eval' is not allowed. ",\
92
+ message: "'eval' is not allowed in Jessie ",\
79
93
},\
80
94
{\
81
95
selector: 'Literal[regex]',\
82
- message: 'regexp literal syntax is not allowed. ',\
96
+ message: 'regexp literal syntax is not allowed in Jessie ',\
83
97
}\
84
98
]\
85
- ,no-ternary: ['error']\
86
99
,no-var: ['error']\
87
100
,guard-for-in: 'off'\
88
101
,semi: ['error', 'always']\
@@ -130,36 +143,50 @@ function indexOfFirstStatement(text) {
130
143
131
144
function isJessie ( text ) {
132
145
const pos = indexOfFirstStatement ( text ) ;
146
+ if ( text . substr ( 0 , pos ) . match ( USE_JESSIE_BEFORE_FIRST_STATEMENT_REGEXP ) ) {
147
+ return true ;
148
+ }
133
149
if ( pos >= 0 ) {
134
- for ( const jessieToken of [ '"use jessie";' , "'use jessie';" ] ) {
135
- if ( text . substr ( pos , jessieToken . length ) === jessieToken ) {
136
- return true ;
137
- }
150
+ if ( USE_JESSIE_FIRST_STATEMENT_REGEXP . test ( text . substr ( pos ) ) ) {
151
+ return true ;
138
152
}
139
153
}
140
154
return false ;
141
155
}
142
156
143
- const filenameIsJessie = new Set ( ) ;
157
+ const prependedText = text => {
158
+ if ( ! isJessie ( text ) ) {
159
+ return '' ;
160
+ }
161
+ let prepend = jessieRulesOneLine ;
162
+ if ( text . startsWith ( '#!' ) ) {
163
+ prepend += '// ' ;
164
+ }
165
+ return prepend ;
166
+ }
167
+
168
+ const filenameToPrepend = new Map ( ) ;
144
169
module . exports = {
145
170
preprocess ( text , filename ) {
146
- if ( isJessie ( text ) ) {
147
- filenameIsJessie . add ( filename ) ;
171
+ const prepend = prependedText ( text ) ;
172
+ if ( prepend ) {
173
+ filenameToPrepend . set ( filename , prepend ) ;
148
174
return [
149
- `${ jessieRulesOneLine } ${ text } `
175
+ `${ prepend } ${ text } `
150
176
] ;
151
177
}
152
- filenameIsJessie . delete ( filename ) ;
178
+ filenameToPrepend . delete ( filename ) ;
153
179
return [ text ] ;
154
180
} ,
155
181
postprocess ( messages , filename ) {
156
- if ( ! filenameIsJessie . has ( filename ) ) {
182
+ if ( ! filenameToPrepend . has ( filename ) ) {
157
183
return [ ] . concat ( ...messages ) ;
158
184
}
185
+ const prepend = filenameToPrepend . get ( filename ) ;
159
186
const rewritten = messages . flatMap ( errors => errors . map ( err => {
160
187
if ( 'fix' in err ) {
161
- // Remove the bytes we inserted.
162
- const range = err . fix . range . map ( offset => offset > jessieRulesOneLine . length ? offset - jessieRulesOneLine . length : offset ) ;
188
+ // Remove the prepension we inserted.
189
+ const range = err . fix . range . map ( offset => Math . max ( offset - prepend . length , 0 ) ) ;
163
190
return { ...err , fix : { ...err . fix , range } } ;
164
191
}
165
192
return err ;
0 commit comments