9
9
// eslint-disable-next-line import/newline-after-import
10
10
const acorn = require ( 'acorn' ) ;
11
11
const jsx = require ( 'acorn-jsx' ) ;
12
- // import { acorn } from 'acorn'; // javascript parser
13
- // import { jsx } from 'acorn-jsx';
14
-
15
12
const JSXParser = acorn . Parser . extend ( jsx ( ) ) ;
16
-
17
13
/**
18
14
* @method throttle
19
15
* @param f A function to throttle
20
16
* @param t A number of milliseconds to use as throttling interval
21
17
* @returns A function that limits input function, `f`, from being called more than once every `t` milliseconds
18
+ *
22
19
*/
23
20
export const throttle = ( f : Function , t : number ) : Function => {
21
+ // Initialize boolean flags for callback, throttledFunc
24
22
let isOnCooldown : boolean = false ;
25
23
let isCallQueued : boolean = false ;
24
+
25
+ // Wrap the passed-in function, f, in a callback function that "throttles"
26
+ // (puts a limit on) the number of calls that can be made to function, f
27
+ // in a given period of time (ms), t
26
28
const throttledFunc = ( ) : any => {
29
+ // CASE 1: In cooldown mode and we already have a function waiting to be executed,
30
+ // so do nothing
27
31
if ( isOnCooldown && isCallQueued ) return ;
32
+
33
+ // CASE 2: In cooldown mode, but we have no functions waiting to be executed,
34
+ // so just make note that we now have a call waiting to be executed and return
28
35
if ( isOnCooldown ) {
29
36
isCallQueued = true ;
30
37
return ;
31
38
}
39
+
40
+ // CASE 3: If we are ready to "fire":
41
+ // Execute the function, f, immediately
32
42
f ( ) ;
43
+ // Initiate a new cooldown period and reset the "call queue"
33
44
isOnCooldown = true ;
34
45
isCallQueued = false ;
46
+
47
+ // Declare a function that checks whether we have
48
+ // another function to be executed right after.
35
49
const runAfterTimeout = ( ) : any => {
36
50
if ( isCallQueued ) {
37
51
isCallQueued = false ;
@@ -42,16 +56,17 @@ export const throttle = (f: Function, t: number): Function => {
42
56
}
43
57
isOnCooldown = false ;
44
58
} ;
59
+
45
60
setTimeout ( runAfterTimeout , t ) ;
46
61
} ;
62
+
47
63
return throttledFunc ;
48
64
} ;
49
65
50
66
// Helper function to grab the getters/setters from `elementType`
51
-
52
67
/**
53
68
* @method getHooksNames
54
- * @param elementType The fiber (whose hooks we want) `type`, A stringified function of the component the Fiber whose hooks we want corresponds to
69
+ * @param elementType The fiber `type`, A stringified function of the component the Fiber whose hooks we want corresponds to
55
70
* @returns An array of strings
56
71
*/
57
72
export const getHooksNames = ( elementType : string ) : Array < string > => {
@@ -60,41 +75,39 @@ export const getHooksNames = (elementType: string): Array<string> => {
60
75
try {
61
76
ast = JSXParser . parse ( elementType ) ;
62
77
} catch ( e ) {
63
- console . error ( `getHooksNames ERROR: Failed to parse elementType string:\n${ elementType } ` ) ;
64
78
return [ 'unknown' ] ;
65
79
}
66
80
67
81
const hooksNames : any = { } ;
68
82
83
+ // Begin search for hook names, only if ast has a body property.
69
84
while ( Object . hasOwnProperty . call ( ast , 'body' ) ) {
70
85
let tsCount : number = 0 ; // Counter for the number of TypeScript hooks seen (to distinguish in masterState)
71
86
ast = ast . body ;
72
- const statements : Array < string > = [ ] ;
73
87
88
+ // Statements get all the names of the hooks. For example: useCount, useWildcard, ...
89
+ const statements : Array < string > = [ ] ;
74
90
/** All module exports always start off as a single 'FunctionDeclaration' type
75
91
* Other types: "BlockStatement" / "ExpressionStatement" / "ReturnStatement"
76
92
* Iterate through AST of every function declaration
77
93
* Check within each function declaration if there are hook declarations */
78
94
ast . forEach ( ( functionDec ) => {
79
95
let body : any ;
80
- if ( functionDec . expression && functionDec . expression . body )
81
- body = functionDec . expression . body . body ;
96
+ if ( functionDec . expression && functionDec . expression . body ) body = functionDec . expression . body . body ;
82
97
else body = functionDec . body ? functionDec . body . body : [ ] ;
83
98
// Traverse through the function's funcDecs and Expression Statements
84
99
body . forEach ( ( elem : any ) => {
100
+ // Hooks will always be contained in a variable declaration
85
101
if ( elem . type === 'VariableDeclaration' ) {
86
102
elem . declarations . forEach ( ( hook : any ) => {
87
- // * TypeScript hooks appear to have no "VariableDeclarator"
88
- // * with id.name of _useState, _useState2, etc...
89
- // * hook.id.type relevant for TypeScript applications
90
- // *
91
- // * Works for useState hooks
103
+ // Parse destructured statements pair
92
104
if ( hook . id . type === 'ArrayPattern' ) {
93
105
hook . id . elements . forEach ( ( hook ) => {
94
106
statements . push ( `_useWildcard${ tsCount } ` ) ;
95
107
statements . push ( hook . name ) ;
96
108
tsCount += 1 ;
97
109
} ) ;
110
+ // Process hook function invocation ?
98
111
} else {
99
112
if ( hook . init . object && hook . init . object . name ) {
100
113
const varName : any = hook . init . object . name ;
0 commit comments