Using Visual Studio Code? Try our new extension by clicking here!
In this post, I want to present an aspect of JavaScript that seems like the language is nice and forgiving at the first glance but is also a source of hard-to-track issues and how DeepCode helps. DeepCode offers an AI-based Static Program Analysis for Java, JavaScript and TypeScript, C/C++, and Python. As you might know, DeepCode uses thousands of open source repos to train our engine.
Let me give you the example first (Btw, it is a real-life example I found here). Try to find the issue:
dart
...
// restore saved {block}s
for (i=saved.length-1; i>=0; i=i-1) {
s = s.replace(new RegExp("~-" + i + "-~"), "{" + saved[i] + "}", "g");
}
...
It is not easy, especially when not being directly pointed at it. Let me give you DeepCode’s suggestion:
replace takes two arguments. Arguments starting with the third one will be ignored.
I have to admit it sparked some interest in me. And I researched the underlying facts. You can find it in the ECMAScript standards but I found this nice summary here:
undefined
javascript
function(a=1, b=2) { /* Function Code */ }
Behind the scenes, JavaScript generates an object called arguments
containing the parameters handed to the function. The arguments
object has properties reflecting the position of the argument in the parameter list.
less
{
0: "First Argument",
1: "Second Argument",
2: "Third Argument"
}
Now, you can see why missing arguments end up as undefined
: You access a non-existent property in an object and get … undefined
. And also how the default value is done.
You can also see what happens to arguments that are overcount and not expected. While they are in the arguments
object, they are simply swallowed. In the above’s example, the global flag of the regex will not make a difference.
The upside of the method is that JavaScript can handle a variable number of input parameters.
The downside is that these kind of bugs are really hard to trace. In our example, you literally see the g
flag, the runtime throws no error, all is hunky-dory.
DeepCode found this issue by learning the expected layout of parameters for the replace()
function as it was changed quite often in open-source repos in lieu of security issues. replace()
is often used to treat external data sources such as request strings and so the engine had a special focus on it.
Coming back to the original heading: All in all, JavaScript is a forgiving language and swallows tons of constructions where the intentions of the developer and the actual effect of the code might differ significantly. Even more dangerous: For Pros using these effects intentionally (as it is safe - mind you it is written in the standard), code might get really hard to understand. Be wary my friends…
Check out how your code is doing and start using DeepCode today.