99// eslint-disable-next-line import/newline-after-import
1010const acorn = require ( 'acorn' ) ;
1111const jsx = require ( 'acorn-jsx' ) ;
12- // import { acorn } from 'acorn'; // javascript parser
13- // import { jsx } from 'acorn-jsx';
1412
1513const JSXParser = acorn . Parser . extend ( jsx ( ) ) ;
1614
@@ -19,19 +17,37 @@ const JSXParser = acorn.Parser.extend(jsx());
1917 * @param f A function to throttle
2018 * @param t A number of milliseconds to use as throttling interval
2119 * @returns A function that limits input function, `f`, from being called more than once every `t` milliseconds
20+ *
2221 */
2322export 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
2630 const throttledFunc = ( ) : any => {
31+ // CASE 1: In cooldown mode and we already have a function waiting to be executed,
32+ // so do nothing
2733 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
2837 if ( isOnCooldown ) {
2938 isCallQueued = true ;
3039 return ;
3140 }
41+
42+ // CASE 3: If we are ready to "fire":
43+ // Execute the function, f, immediately
3244 f ( ) ;
45+ // Initiate a new cooldown period and reset the "call queue"
3346 isOnCooldown = true ;
3447 isCallQueued = false ;
48+
49+ // Declare a function that checks whether we have
50+ // another function to be executed right after.
3551 const runAfterTimeout = ( ) : any => {
3652 if ( isCallQueued ) {
3753 isCallQueued = false ;
@@ -42,59 +58,58 @@ export const throttle = (f: Function, t: number): Function => {
4258 }
4359 isOnCooldown = false ;
4460 } ;
61+
4562 setTimeout ( runAfterTimeout , t ) ;
4663 } ;
64+
4765 return throttledFunc ;
4866} ;
4967
5068// Helper function to grab the getters/setters from `elementType`
51-
5269/**
5370 * @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
5673 */
5774export const getHooksNames = ( elementType : string ) : Array < string > => {
5875 // Initialize empty object to store the setters and getter
5976 let ast : any ;
6077 try {
6178 ast = JSXParser . parse ( elementType ) ;
6279 } catch ( e ) {
63- console . error ( `getHooksNames ERROR: Failed to parse elementType string:\n${ elementType } ` ) ;
6480 return [ 'unknown' ] ;
6581 }
6682
6783 const hooksNames : any = { } ;
6884
85+ // Begin search for hook names, only if ast has a body property.
6986 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)
7188 ast = ast . body ;
72- const statements : Array < string > = [ ] ;
7389
90+ // Statements get all the names of the hooks. For example: useCount, useWildcard, ...
91+ const statements : Array < string > = [ ] ;
7492 /** All module exports always start off as a single 'FunctionDeclaration' type
7593 * Other types: "BlockStatement" / "ExpressionStatement" / "ReturnStatement"
7694 * Iterate through AST of every function declaration
7795 * Check within each function declaration if there are hook declarations */
78- ast . forEach ( ( functionDec ) => {
96+ ast . forEach ( functionDec => {
7997 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 ;
8299 else body = functionDec . body ? functionDec . body . body : [ ] ;
83100 // Traverse through the function's funcDecs and Expression Statements
84101 body . forEach ( ( elem : any ) => {
102+ // Hooks will always be contained in a variable declaration
85103 if ( elem . type === 'VariableDeclaration' ) {
86104 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
92106 if ( hook . id . type === 'ArrayPattern' ) {
93107 hook . id . elements . forEach ( ( hook ) => {
94108 statements . push ( `_useWildcard${ tsCount } ` ) ;
95109 statements . push ( hook . name ) ;
96110 tsCount += 1 ;
97111 } ) ;
112+ // Process hook function invocation ?
98113 } else {
99114 if ( hook . init . object && hook . init . object . name ) {
100115 const varName : any = hook . init . object . name ;
0 commit comments