← All posts

DeepSource JavaScript analyzer lands in beta

DeepSource now supports JavaScript, React and TypeScript, with 470+ types of issues.

Header image
By Siddhant on 
Share on Twitter Share on LinkedIn Share on Facebook

When writing code, it’s hardly sometimes that our code executes successfully in the first run. And then, after every execution failure of the code, we dive into the error log to find where the bug resides. Unfortunately, we end up spending more time on resolving bugs than what is actually needed. And this has been really common in the case of JavaScript.

As developers, we ensure code quality with the help of unit and functional testing. We can complement these test plans with static analysis through which we can now check the code before its execution to assess its quality and its adherence to coding standards. Static analysis helps us find the issues in our code that we humans can’t always spot by ourselves and thus, ensures code quality throughout the project along with maintaining developer efficiency.

Today, we are really excited to launch continuous static analysis for JavaScript, detecting 470+ issues, like bug risks, anti-patterns, performance and style issues.

DeepSource JavaScript Analysis Results

Supported Frameworks and Language Standards

  • All the versions of ECMAScript (ES3, ES5, ES2015 - ES2020)
  • React JSX
  • TypeScript
  • All major module systems ( CommonJS, ES modules and AMD)
  • Popular JavaScript style guides (Airbnb, Google and Standard)

ESLint Rules & Plugins

DeepSource JavaScript analyzer fully supports all the ESLint core JavaScript rules and is 100% ESLint compatible. Along with that, it currently supports the following ESLint plugins :

We are working to add support for more plugins in order to improve the analysis further.

Using the JavaScript analyzer

To start analyzing your JavaScript code, create an account on DeepSource, enable the javascript analyzer in your .deepsource.toml file, and activate analysis.

Sample Configuration (.deepsource.toml)

version = 1

test_patterns = ["*/test/**"]

exclude_patterns = [
    "public/**,",
    "dist/**"
]

[[analyzers]]
name = "javascript"
enabled = true

  [analyzers.meta]
  ecma_version = "2016"
  module_system = "commonjs"
  environment = [
    "nodejs",
    "browser",
    "jest",
  ]

  plugins = ["react"]
  style_guide = "airbnb"
  dialect = "typescript"

Here’s a few issues detected by the analyzer:

Bug-risks

  1. Debugger should not be used in production code

    The debugger statement is used to tell the executing JavaScript environment to stop execution and start up a debugger at the current point in the code. Having

    it in the production code can stop the browser from executing code and opens an appropriate debugger.

    Example :

    function isTruthy(x) {
        debugger;
        return Boolean(x);
    }
    
  2. Prevent reassigning function declarations

    Overwriting/Reassigning a function is often indicative of a mistake or issue. It can cause bugs in the code at runtime.

    Example :

    function foo() {}
    foo = bar;
    
    function foo() {
        foo = bar;
    }
    
  3. Using constant condition in conditional statements

    A constant expression (for example, a literal) as a test condition might be a typo or development trigger for a specific behavior. It may break the code during the runtime.

    Example :

    if (false) {
        doSomethingUnfinished();
    }
    
    if (void x) {
        doSomethingUnfinished();
    }
    
    do {
        doSomethingForever();
    } while (x = -1);
    

Anti-patterns

  1. Prefer the usage of === and !== instead of == and !=

    It is considered good practice to use the type-safe equality operators === and !== instead of their regular counterparts == and !=. For instance, these statements which ideally should be false are

    considered true :

    [] == false
    [] == ![]
    3 == "03"
    
  2. Prevent the usage of alert

    JavaScript’s alert, confirm, and prompt functions are widely considered to be obtrusive as UI elements and should not be used in production code. They should be replaced by a custom implementation.

    Example :

    alert("here!");
    
    confirm("Are you sure?");
    
    prompt("What's your name?", "John Doe");
    
    should be replaced by -
    
    customalert("here!")
    
    customconfirm("Are you sure?")
    
    customprompt("What's your name?", "John Doe")
    
  3. Prevent the usage of new for Side Effects

    We use new with a constructor to create an object of a particular type and store that object in a variable, such as:

    var car = new Car();

    It is of no use to use new like this :

    new Car();

    In this case, the created object is thrown away because its reference isn’t stored anywhere

Security

  1. Prevent the usage of eval

    JavaScript’s eval() function is potentially dangerous and is often misused. Using eval() on untrusted code can open a program up to several different injection attacks. The use of eval() in most contexts can be substituted for a better, alternative approach to a problem.

    Example :

    var obj = { x: "foo" },
        key = "x",
        value = eval("obj." + key);
    
  2. Prevent the usage of Script URLs

    Using javascript: URLs is considered by some as a form of eval. Code passed in javascript: URLs has to be parsed and evaluated by the browser in the same way that eval is processed. Also, assembling javascript: URLs (or other strings that contain source code) is a tricky task which is prone to XSS vulnerabilities.

    Example :

    location.href = "javascript:void(0)";
    
  3. Prevent the usage of implied-eval

    Try to eliminate implied eval() through the use of setTimeout(), setInterval() or execScript(). As such, it will warn when either function is used with a string as the first argument.

    Example :

    setTimeout("alert('Hi!');", 100);
    
    setInterval("alert('Hi!');", 100);
    
    execScript("alert('Hi!')");
    
    can be replaced by :
    
    setTimeout(function() {
        alert("Hi!");
    }, 100);
    
    setInterval(function() {
        alert("Hi!");
    }, 100);
    

Performance

  1. Detect unreachable code after return, throw, continue, and break statements

    Because the return, throw, break, and continue statements unconditionally exit a block of code, any statements after them cannot be executed. Detecting and removing them helps to improve the performance of the code.

    function hello() {
        let x = 3
        return x
        x = 5.           // Never executed
        console.log(x).  // Never executed
    }
    
  2. Detect the unused variables

    Variables that are declared and not used anywhere in the code are most likely an error due to incomplete refactoring. Such variables take up space in the code and cause confusion.

    Example :

    // x is declared but is never used
    var x;
    var i;
    for(i=1;i<=100;i++){
        console.log("Hello");
    }
    
  3. Detect empty function declarations and block statements

    Empty functions can reduce readability and also end up taking up space which is of no use. Empty block statements, while not technically errors, usually occur due to refactoring that wasn’t completed. They can cause confusion when reading code and can affect the performance too.

    Example :

    function foo() {}
    
    var foo = function() {};
    
    var foo = () => {};
    
    if (foo) {
    }
    
    while (foo) {
    }
    

Upcoming releases

We’re continuously improving the analyzer and here’s a near future roadmap:

  • Add support for Angular, Flow, Vue and other popular frameworks.
  • Autofix support for commonly occurred issues.
  • Automated code formatting support for Prettier and Standard JS.

We’re very excited about this release, and hope that this will help you prevent issues in your code, and make writing JavaScript even more fun! Head over to the docs or tell us what you think; Feedback/suggestions/bugs - discuss.deepsource.io

About DeepSource
DeepSource helps you automatically find and fix issues in your code during code reviews, such as bug risks, anti-patterns, performance issues, and security flaws. It takes less than 5 minutes to set up with your Bitbucket, GitHub, or GitLab account. It works for Python, Go, Ruby, and JavaScript.
Get started for free

Keep reading...