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