Static Analysis for Javascript frontend frameworks
Good day,
I have been able to setup WALA locally using the wala-start repo, and do analysis of a simple javascript function. However, I'm trying to use WALA to generate the call graph/ir for a simple React code snippet but it doesn't work. Any pointers is very much appreciated.
Thanks.
Hi @Fakorede if you could give more specific info on what goes wrong that would be helpful. I wouldn't be surprised if WALA runs into scalability issues as React codes can be huge if you include the full React library.
Thanks for your response Professor @msridhar. I am using the below code to generate IR:
public static void generateIR(String filename) throws ClassHierarchyException {
JSCallGraphUtil.setTranslatorFactory(
new CAstRhinoTranslatorFactory());
IClassHierarchy cha =
JSCallGraphUtil.makeHierarchyForScripts(filename);
IRFactory<IMethod> factory = AstIRFactory.makeDefaultFactory();
for (IClass klass : cha) {
if (!klass.getName().toString().startsWith("prologue.js")) {
IMethod m = klass.getMethod(AstMethodReference.fnSelector);
if (m != null) {
IR ir = factory.makeIR(m, Everywhere.EVERYWHERE,
new SSAOptions());
System.out.println(ir);
}
}
}
}
I have created a file which contains a simple javascript function (as below), tested it and works quite alright
function testFunctionWithCallback() {
var b = 3
var c = 5
var a = f(b * c)
}
If I replace the the js function with a sample react code snippet as below, i observe the IMethod for every IClass is null.
import { useState } from 'react';
export default function Form() {
const [answer, setAnswer] = useState('');
const [error, setError] = useState(null);
const [status, setStatus] = useState('typing');
if (status === 'success') {
return <h1>That's right!</h1>
}
async function handleSubmit(e) {
e.preventDefault();
setStatus('submitting');
try {
await submitForm(answer);
setStatus('success');
} catch (err) {
setStatus('typing');
setError(err);
}
}
function handleTextareaChange(e) {
setAnswer(e.target.value);
}
return (
<>
<h2>City quiz</h2>
<p>
In which city is there a billboard that turns air into drinkable water?
</p>
<form onSubmit={handleSubmit}>
<textarea
value={answer}
onChange={handleTextareaChange}
disabled={status === 'submitting'}
/>
<br />
<button disabled={
answer.length === 0 ||
status === 'submitting'
}>
Submit
</button>
{error !== null &&
<p className="Error">
{error.message}
</p>
}
</form>
</>
);
}
function submitForm(answer) {
// Pretend it's hitting the network.
return new Promise((resolve, reject) => {
setTimeout(() => {
let shouldError = answer.toLowerCase() !== 'lima'
if (shouldError) {
reject(new Error('Good guess but a wrong answer. Try again!'));
} else {
resolve();
}
}, 1500);
});
}
Output attached below. Thanks sir.