-
-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
143 additions
and
229 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
222 changes: 112 additions & 110 deletions
222
src/backend/helpers.js → src/backend/helpers.ts
100755 → 100644
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,110 +1,112 @@ | ||
/* eslint-disable linebreak-style */ | ||
/* eslint-disable no-shadow */ | ||
/* eslint-disable max-len */ | ||
/* eslint-disable no-console */ | ||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||
/* eslint-disable @typescript-eslint/no-var-requires */ | ||
/* eslint-disable linebreak-style */ | ||
/* eslint-disable no-inner-declarations, no-loop-func */ | ||
// eslint-disable-next-line import/newline-after-import | ||
const acorn = require('acorn'); | ||
const jsx = require('acorn-jsx'); | ||
// import { acorn } from 'acorn'; // javascript parser | ||
// import { jsx } from 'acorn-jsx'; | ||
|
||
const JSXParser = acorn.Parser.extend(jsx()); | ||
|
||
// Returns a throttled version of an input function | ||
// The returned throttled function only executes at most once every t milliseconds | ||
export const throttle = (f, t) => { | ||
let isOnCooldown = false; | ||
let isCallQueued = false; | ||
const throttledFunc = () => { | ||
if (isOnCooldown && isCallQueued) return; | ||
if (isOnCooldown) { | ||
isCallQueued = true; | ||
return; | ||
} | ||
f(); | ||
isOnCooldown = true; | ||
isCallQueued = false; | ||
|
||
const runAfterTimeout = () => { | ||
if (isCallQueued) { | ||
isCallQueued = false; | ||
isOnCooldown = true; // not needed I think | ||
f(); | ||
setTimeout(runAfterTimeout, t); | ||
return; | ||
} | ||
isOnCooldown = false; | ||
}; | ||
setTimeout(runAfterTimeout, t); | ||
}; | ||
return throttledFunc; | ||
}; | ||
|
||
// Helper function to grab the getters/setters from `elementType` | ||
export const getHooksNames = (elementType) => { | ||
// Initialize empty object to store the setters and getter | ||
let ast; | ||
try { | ||
ast = JSXParser.parse(elementType); | ||
} catch (e) { | ||
return ['unknown']; | ||
} | ||
const hookState = {}; | ||
const hooksNames = {}; | ||
|
||
while (Object.hasOwnProperty.call(ast, 'body')) { | ||
let tsCount = 0; // Counter for the number of TypeScript hooks seen (to distinguish in masterState) | ||
ast = ast.body; | ||
const statements = []; | ||
|
||
/** All module exports always start off as a single 'FunctionDeclaration' type | ||
* Other types: "BlockStatement" / "ExpressionStatement" / "ReturnStatement" | ||
* Iterate through AST of every function declaration | ||
* Check within each function declaration if there are hook declarations */ | ||
ast.forEach((functionDec) => { | ||
let body; | ||
if (functionDec.expression && functionDec.expression.body) | ||
body = functionDec.expression.body.body; | ||
else body = functionDec.body ? functionDec.body.body : []; | ||
// Traverse through the function's funcDecs and Expression Statements | ||
body.forEach((elem) => { | ||
if (elem.type === 'VariableDeclaration') { | ||
elem.declarations.forEach((hook) => { | ||
// * TypeScript hooks appear to have no "VariableDeclarator" | ||
// * with id.name of _useState, _useState2, etc... | ||
// * hook.id.type relevant for TypeScript applications | ||
// * | ||
// * Works for useState hooks | ||
if (hook.id.type === 'ArrayPattern') { | ||
hook.id.elements.forEach((hook) => { | ||
statements.push(hook.name); | ||
// * Unshift a wildcard name to achieve similar functionality as before | ||
statements.unshift(`_useWildcard${tsCount}`); | ||
tsCount += 1; | ||
}); | ||
} else { | ||
if (hook.init.object && hook.init.object.name) { | ||
const varName = hook.init.object.name; | ||
if (!hooksNames[varName] && varName.match(/_use/)) { | ||
hooksNames[varName] = hook.id.name; | ||
} | ||
} | ||
if (hook.id.name !== undefined) { | ||
statements.push(hook.id.name); | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
statements.forEach((el, i) => { | ||
if (el.match(/_use/)) hookState[el] = statements[i + 2]; | ||
}); | ||
}); | ||
} | ||
return Object.values(hooksNames); | ||
}; | ||
/* eslint-disable linebreak-style */ | ||
/* eslint-disable no-shadow */ | ||
/* eslint-disable max-len */ | ||
/* eslint-disable no-console */ | ||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||
/* eslint-disable @typescript-eslint/no-var-requires */ | ||
/* eslint-disable linebreak-style */ | ||
/* eslint-disable no-inner-declarations, no-loop-func */ | ||
// eslint-disable-next-line import/newline-after-import | ||
const acorn = require('acorn'); | ||
const jsx = require('acorn-jsx'); | ||
// import { acorn } from 'acorn'; // javascript parser | ||
// import { jsx } from 'acorn-jsx'; | ||
|
||
const JSXParser = acorn.Parser.extend(jsx()); | ||
|
||
// Returns a throttled version of an input function | ||
// The returned throttled function only executes at most once every t milliseconds | ||
export const throttle = (f : Function, t: number) : Function => { | ||
let isOnCooldown : boolean = false; | ||
let isCallQueued : boolean = false; | ||
const throttledFunc = () : any => { | ||
if (isOnCooldown && isCallQueued) return; | ||
if (isOnCooldown) { | ||
isCallQueued = true; | ||
return; | ||
} | ||
f(); | ||
isOnCooldown = true; | ||
isCallQueued = false; | ||
const runAfterTimeout = () : any => { | ||
if (isCallQueued) { | ||
isCallQueued = false; | ||
isOnCooldown = true; // not needed I think | ||
f(); | ||
setTimeout(runAfterTimeout, t); | ||
return; | ||
} | ||
isOnCooldown = false; | ||
}; | ||
setTimeout(runAfterTimeout, t); | ||
}; | ||
return throttledFunc; | ||
}; | ||
|
||
// Helper function to grab the getters/setters from `elementType` | ||
export const getHooksNames = (elementType : string) : Array<string> => { | ||
// Initialize empty object to store the setters and getter | ||
let ast : any; | ||
try { | ||
ast = JSXParser.parse(elementType); | ||
} catch (e) { | ||
return ['unknown']; | ||
} | ||
|
||
// const hookState = {}; | ||
// const hooksNames = {}; | ||
const hookState: any = {}; | ||
const hooksNames: any = {}; | ||
|
||
while (Object.hasOwnProperty.call(ast, 'body')) { | ||
let tsCount : number = 0; // Counter for the number of TypeScript hooks seen (to distinguish in masterState) | ||
ast = ast.body; | ||
const statements : Array<string> = []; | ||
|
||
/** All module exports always start off as a single 'FunctionDeclaration' type | ||
* Other types: "BlockStatement" / "ExpressionStatement" / "ReturnStatement" | ||
* Iterate through AST of every function declaration | ||
* Check within each function declaration if there are hook declarations */ | ||
ast.forEach((functionDec) => { | ||
let body : any; | ||
if (functionDec.expression && functionDec.expression.body) | ||
body = functionDec.expression.body.body; | ||
else body = functionDec.body ? functionDec.body.body : []; | ||
// Traverse through the function's funcDecs and Expression Statements | ||
body.forEach((elem : any) => { | ||
if (elem.type === 'VariableDeclaration') { | ||
elem.declarations.forEach((hook : any) => { | ||
// * TypeScript hooks appear to have no "VariableDeclarator" | ||
// * with id.name of _useState, _useState2, etc... | ||
// * hook.id.type relevant for TypeScript applications | ||
// * | ||
// * Works for useState hooks | ||
if (hook.id.type === 'ArrayPattern') { | ||
hook.id.elements.forEach((hook) => { | ||
statements.push(hook.name); | ||
// * Unshift a wildcard name to achieve similar functionality as before | ||
statements.unshift(`_useWildcard${tsCount}`); | ||
tsCount += 1; | ||
}); | ||
} else { | ||
if (hook.init.object && hook.init.object.name) { | ||
const varName : any = hook.init.object.name; | ||
if (!hooksNames[varName] && varName.match(/_use/)) { | ||
hooksNames[varName] = hook.id.name; | ||
} | ||
} | ||
if (hook.id.name !== undefined) { | ||
statements.push(hook.id.name); | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
statements.forEach((el, i) => { | ||
if (el.match(/_use/)) hookState[el] = statements[i + 2]; | ||
}); | ||
}); | ||
} | ||
return Object.values(hooksNames); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.