7
7
*/
8
8
9
9
// Only used for types
10
- // eslint-disable-next-line
10
+ /* eslint-disable import/no-extraneous-dependencies */
11
11
import { NodePath , Visitor } from '@babel/traverse' ;
12
- // eslint-disable-next-line
13
12
import { Identifier } from '@babel/types' ;
14
-
15
- const invariant = ( condition : unknown , message : string ) => {
16
- if ( ! condition ) {
17
- throw new Error ( 'babel-plugin-jest-hoist: ' + message ) ;
18
- }
19
- } ;
13
+ /* eslint-enable */
20
14
21
15
// We allow `jest`, `expect`, `require`, all default Node.js globals and all
22
16
// ES2015 built-ins to be used inside of a `jest.mock` factory.
23
17
// We also allow variables prefixed with `mock` as an escape-hatch.
24
- const WHITELISTED_IDENTIFIERS : Set < string > = new Set ( [
25
- 'Array' ,
26
- 'ArrayBuffer ',
27
- 'Boolean ',
28
- 'DataView ',
29
- 'Date ',
30
- 'Error ',
31
- 'EvalError ',
32
- 'Float32Array ',
33
- 'Float64Array ',
34
- 'Function ',
35
- 'Generator ',
36
- 'GeneratorFunction ',
37
- 'Infinity ',
38
- 'Int16Array ',
39
- 'Int32Array ',
40
- 'Int8Array ',
41
- 'InternalError ',
42
- 'Intl ',
43
- 'JSON ',
44
- 'Map ',
45
- 'Math ',
46
- 'NaN ',
47
- 'Number ',
48
- 'Object ',
49
- 'Promise ',
50
- 'Proxy ',
51
- 'RangeError ',
52
- 'ReferenceError ',
53
- 'Reflect ',
54
- 'RegExp ',
55
- 'Set ',
56
- 'String ',
57
- 'Symbol ',
58
- 'SyntaxError ',
59
- 'TypeError ',
60
- 'URIError ',
61
- 'Uint16Array ',
62
- 'Uint32Array ',
63
- 'Uint8Array ',
64
- 'Uint8ClampedArray ',
65
- 'WeakMap ',
66
- 'WeakSet ',
67
- 'arguments ',
68
- 'console ',
69
- 'expect ',
70
- 'isNaN ',
71
- 'jest ',
72
- 'parseFloat ',
73
- 'parseInt ',
74
- 'require ',
75
- 'undefined ',
76
- ] ) ;
77
- Object . getOwnPropertyNames ( global ) . forEach ( name => {
78
- WHITELISTED_IDENTIFIERS . add ( name ) ;
79
- } ) ;
18
+ const WHITELISTED_IDENTIFIERS = new Set < string > (
19
+ [
20
+ 'Array ',
21
+ 'ArrayBuffer ',
22
+ 'Boolean ',
23
+ 'DataView ',
24
+ 'Date ',
25
+ 'Error ',
26
+ 'EvalError ',
27
+ 'Float32Array ',
28
+ 'Float64Array ',
29
+ 'Function ',
30
+ 'Generator ',
31
+ 'GeneratorFunction ',
32
+ 'Infinity ',
33
+ 'Int16Array ',
34
+ 'Int32Array ',
35
+ 'Int8Array ',
36
+ 'InternalError ',
37
+ 'Intl ',
38
+ 'JSON ',
39
+ 'Map ',
40
+ 'Math ',
41
+ 'NaN ',
42
+ 'Number ',
43
+ 'Object ',
44
+ 'Promise ',
45
+ 'Proxy ',
46
+ 'RangeError ',
47
+ 'ReferenceError ',
48
+ 'Reflect ',
49
+ 'RegExp ',
50
+ 'Set ',
51
+ 'String ',
52
+ 'Symbol ',
53
+ 'SyntaxError ',
54
+ 'TypeError ',
55
+ 'URIError ',
56
+ 'Uint16Array ',
57
+ 'Uint32Array ',
58
+ 'Uint8Array ',
59
+ 'Uint8ClampedArray ',
60
+ 'WeakMap ',
61
+ 'WeakSet ',
62
+ 'arguments ',
63
+ 'console ',
64
+ 'expect ',
65
+ 'isNaN ',
66
+ 'jest ',
67
+ 'parseFloat ',
68
+ 'parseInt ',
69
+ 'require ',
70
+ 'undefined' ,
71
+ ... Object . getOwnPropertyNames ( global ) ,
72
+ ] . sort ( ) ,
73
+ ) ;
80
74
81
75
const JEST_GLOBAL = { name : 'jest' } ;
82
76
// TODO: Should be Visitor<{ids: Set<NodePath<Identifier>>}>, but `ReferencedIdentifier` doesn't exist
@@ -93,15 +87,18 @@ const FUNCTIONS: Record<
93
87
( args : Array < NodePath > ) => boolean
94
88
> = Object . create ( null ) ;
95
89
96
- FUNCTIONS . mock = ( args : Array < NodePath > ) => {
90
+ FUNCTIONS . mock = args => {
97
91
if ( args . length === 1 ) {
98
92
return args [ 0 ] . isStringLiteral ( ) || args [ 0 ] . isLiteral ( ) ;
99
93
} else if ( args . length === 2 || args . length === 3 ) {
100
94
const moduleFactory = args [ 1 ] ;
101
- invariant (
102
- moduleFactory . isFunction ( ) ,
103
- 'The second argument of `jest.mock` must be an inline function.' ,
104
- ) ;
95
+
96
+ if ( ! moduleFactory . isFunction ( ) ) {
97
+ throw moduleFactory . buildCodeFrameError (
98
+ 'The second argument of `jest.mock` must be an inline function.\n' ,
99
+ TypeError ,
100
+ ) ;
101
+ }
105
102
106
103
const ids : Set < NodePath < Identifier > > = new Set ( ) ;
107
104
const parentScope = moduleFactory . parentPath . scope ;
@@ -122,23 +119,28 @@ FUNCTIONS.mock = (args: Array<NodePath>) => {
122
119
}
123
120
124
121
if ( ! found ) {
125
- invariant (
122
+ const isAllowedIdentifier =
126
123
( scope . hasGlobal ( name ) && WHITELISTED_IDENTIFIERS . has ( name ) ) ||
127
- / ^ m o c k / i. test ( name ) ||
128
- // Allow istanbul's coverage variable to pass.
129
- / ^ (?: _ _ ) ? c o v / . test ( name ) ,
130
- 'The module factory of `jest.mock()` is not allowed to ' +
131
- 'reference any out-of-scope variables.\n' +
132
- 'Invalid variable access: ' +
133
- name +
134
- '\n' +
135
- 'Whitelisted objects: ' +
136
- Array . from ( WHITELISTED_IDENTIFIERS ) . join ( ', ' ) +
137
- '.\n' +
138
- 'Note: This is a precaution to guard against uninitialized mock ' +
139
- 'variables. If it is ensured that the mock is required lazily, ' +
140
- 'variable names prefixed with `mock` (case insensitive) are permitted.' ,
141
- ) ;
124
+ / ^ m o c k / i. test ( name ) ||
125
+ // Allow istanbul's coverage variable to pass.
126
+ / ^ (?: _ _ ) ? c o v / . test ( name ) ;
127
+
128
+ if ( ! isAllowedIdentifier ) {
129
+ throw id . buildCodeFrameError (
130
+ 'The module factory of `jest.mock()` is not allowed to ' +
131
+ 'reference any out-of-scope variables.\n' +
132
+ 'Invalid variable access: ' +
133
+ name +
134
+ '\n' +
135
+ 'Whitelisted objects: ' +
136
+ Array . from ( WHITELISTED_IDENTIFIERS ) . join ( ', ' ) +
137
+ '.\n' +
138
+ 'Note: This is a precaution to guard against uninitialized mock ' +
139
+ 'variables. If it is ensured that the mock is required lazily, ' +
140
+ 'variable names prefixed with `mock` (case insensitive) are permitted.\n' ,
141
+ ReferenceError ,
142
+ ) ;
143
+ }
142
144
}
143
145
}
144
146
@@ -147,13 +149,10 @@ FUNCTIONS.mock = (args: Array<NodePath>) => {
147
149
return false ;
148
150
} ;
149
151
150
- FUNCTIONS . unmock = ( args : Array < NodePath > ) =>
151
- args . length === 1 && args [ 0 ] . isStringLiteral ( ) ;
152
- FUNCTIONS . deepUnmock = ( args : Array < NodePath > ) =>
153
- args . length === 1 && args [ 0 ] . isStringLiteral ( ) ;
154
- FUNCTIONS . disableAutomock = FUNCTIONS . enableAutomock = (
155
- args : Array < NodePath > ,
156
- ) => args . length === 0 ;
152
+ FUNCTIONS . unmock = args => args . length === 1 && args [ 0 ] . isStringLiteral ( ) ;
153
+ FUNCTIONS . deepUnmock = args => args . length === 1 && args [ 0 ] . isStringLiteral ( ) ;
154
+ FUNCTIONS . disableAutomock = FUNCTIONS . enableAutomock = args =>
155
+ args . length === 0 ;
157
156
158
157
export = ( ) => {
159
158
const shouldHoistExpression = ( expr : NodePath ) : boolean => {
0 commit comments