Static Analysis in JavaScript: What’s Easy and What’s Hard

Rate this content
Bookmark

We are all using static analysis tools like ESLint every day to ensure the better quality of our code. How does it work, and what is tricky about JavaScript, making writing a proper rule often not trivial?

FAQ

Static code analysis is a process where a program, typically referred to as a static code analyzer, examines source code without actually executing it. It analyzes the code to produce metrics, identify problems, or generate warnings, based on the code's syntax and structure.

Static analysis inspects code without executing it, often using models like text, tokens, or syntax trees to evaluate code quality and security. Dynamic analysis, on the other hand, involves executing code and typically includes techniques like unit tests and code coverage to find issues that only appear during execution.

Static analysis in JavaScript can be conducted at several levels: text-based, token-based, syntax tree (AST), semantic, control flow analysis, and data flow analysis. Each level builds upon the previous one to provide more detailed and nuanced insights into the code's behavior and quality.

JavaScript's dynamic nature can make static analysis challenging, especially in the absence of explicit types and the need to handle JavaScript's unusual behaviors and quirks. Implementing comprehensive and effective analysis rules often requires handling a wide array of special cases and configurations.

Some static analysis rules may generate too many false positives or may not perform adequately due to limitations in understanding complex or dynamic code patterns. Such rules are often disabled by default to avoid overwhelming developers with misleading or incorrect warnings.

The 'No New Symbol' rule in JavaScript static analysis reports an error whenever the 'new' keyword is used with 'Symbol', which should only be used directly without 'new'. This rule helps prevent runtime exceptions from incorrect usage of symbols.

Static analysis helps improve code quality by detecting potential errors, enforcing coding standards, and suggesting optimizations without running the code. It aids developers in maintaining code cleanliness, security, and consistency throughout the development process.

An Abstract Syntax Tree (AST) is a tree representation of the abstract syntactic structure of JavaScript code. In static analysis, ASTs are used to deeply understand the syntax and structure of code, which enables more precise analysis and rule application.

While static analysis can detect many types of errors and code quality issues, it cannot catch every possible error, especially those that only manifest during runtime or depend on specific execution paths or external inputs.

Developers can contribute to static analysis tools by writing custom rules, improving existing analysis algorithms, or integrating new features that enhance code evaluation capabilities. Contributions help adapt tools to evolving coding practices and language features.

Elena Vilchik
Elena Vilchik
23 min
05 Jun, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

Static analysis in JavaScript involves analyzing source code without executing it, producing metrics, problems, or warnings. Data flow analysis aims to determine the values of data in a program. Rule implementation in JavaScript can be straightforward or require extensive consideration of various cases and parameters. JavaScript's dynamic nature and uncertainty make static analysis challenging, but it can greatly improve code quality.

1. Introduction to Static Analysis in JavaScript

Short description:

Hello, everybody. My name is Elena Vilchik and I'm going to talk to you about static analysis in JavaScript. I'm working at the Cynar company, writing analyzers for JavaScript and other languages. Static code analysis is a program that analyzes source code without executing it, producing metrics, problems, or warnings. It is different from dynamic analysis, which executes code. There are different levels of static analysis, including text-based, token-based, syntax tree, and semantic analysis. Control flow analysis is a less commonly used model.

Hello, everybody. My name is Elena Vilchik and I'm going to talk to you about static analysis in JavaScript. So, I'm going to talk about what's easy and what's hard there. So, a bit about myself, I'm working at the Cynar company. We're doing the platform for continuous code quality and security detection. More than eight years I'm writing analyzers for JavaScript and many other languages, and when it comes to the clean code, some people can call me a pain in the neck.

So before we jump to the what is easy and what is hard, I want to first tell you what static code analysis is. Not everybody might be aware of that. So, static code analyzer is a program, as you might have guessed, which takes the source code, the text files of the program. Sometimes for some languages it takes something else. Some precompiled files, for example bytecode for Java, to get some semantic information produced by the compiler. And without actual execution of the source code, it might have some imitation of the execution, but never actually executing the source code, it produces some metrics, problems or warnings, findings, so whatever you call them. You might also think about, okay, static analysis, I get it, then what is dynamic analysis and if those are some competing directions of the same thing, in fact no, dynamic analysis you're using it every day, this is something which actually executes a code and examples also that are known to everybody, this is code coverage, those are unit tests, and in fact those two things are required to everybody and big friends and helpers to every developer in everyday life.

I'm going to go through the levels of static analysis, levels in terms of the models which is used for writing. We are going to use the term rule which is familiar to everybody. The first level will be text-based when you just get the source file and you try to infer something from there. This can be, for example, this example could be the number of lines in the file or the presence of the license header. To get those things, you don't need to know anything else but just the text of the source code. The next level will be tokens. You're splitting it into words. You know some metadata about those tokens if it is a keyword, dictator, and you can already know, write some rules on this level. For example, for the string literal, you can say that, okay, I have this literal token and I can tell you if it's using the right quotes which is single quote or double quote, whatever you configure it. The next level is the syntax tree or abstract syntax tree, IST for short. This is super common, the most used level where we represent the source code in the tree format. Here is the example, a bit simplified of course for the shortness of the code which we just had before. So we have function which has name foo and parameter p which has a body. If statement has condition with a quality operator and those has operands, p untrue and a call function. So for those who didn't know I would really recommend to have a look at the IST Explorer website, super great website which will display you the IST representation of the source code whatever you're going to put there, super nice to even to investigate some new features of language to see like what is actually the thing which you just entered there, which kind of syntax of language it is. there is a level of semantic, semantic we're talking about rivals, their declarations, usages and on this level for example you know that here is the parameter P, it is declared here, it is used here, then there is a function foo which is declared and referenced at the last line and the variable P which is not the same as parameter P even if they have same name, here they are declared in different scopes, scope is another notion of this level and here it is written and declared and here it is read. And then we are talking about more dance models which are usually not as widely used as all previous ones, the most common of them is control flow analysis which is for example present in the core of ESLint.

2. Understanding Data Flow Analysis

Short description:

On this level, we are aware of the order of execution of instructions, expressions, and statements. Data flow analysis aims to determine the values of data in a program. TypeScript compiler performs dataflow analysis to check variable types based on control flow. Each level builds upon the previous one, with control flow analysis being a prerequisite for dataflow analysis.

On this level we are aware of the order of execution of instructions, execution of expressions and statements or our example with if statement, inside the foo function we have the condition p equals true and depending if it's true, we're gonna alert it, if it's not, we gonna alert we can exit as well. So this is, the last level I wanted to talk about, last model is data flow analysis.

In this level we want to know the values, the maximum we can learn about the values of the values of data, in other words of the program. Of course we cannot know everything because nobody knows everything until you actually execute the program, but you can know something about the values. For example in this block of if equal true we will know that p is actually a true value, in the else we will know that it is not true. Outside of this if we will not know anything about p value. You can also think of TypeScript compiler as a dataflow analysis, because that's what it does. It looks at the control flow of the program and checks depending on the different statements, different expressions, what are the limits to the type of the variable. And here the notion between value and type is pretty fuzzy, because of the way TypeScript defined it. And as you might have noticed, every next level is based on the previous one to be able to build the dataflow analysis, you need to have control flow analysis necessarily, and etc.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Modern Web Debugging
JSNation 2023JSNation 2023
29 min
Modern Web Debugging
Top Content
Few developers enjoy debugging, and debugging can be complex for modern web apps because of the multiple frameworks, languages, and libraries used. But, developer tools have come a long way in making the process easier. In this talk, Jecelyn will dig into the modern state of debugging, improvements in DevTools, and how you can use them to reliably debug your apps.
The Future of Performance Tooling
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
Top Content
Our understanding of performance & user-experience has heavily evolved over the years. Web Developer Tooling needs to similarly evolve to make sure it is user-centric, actionable and contextual where modern experiences are concerned. In this talk, Addy will walk you through Chrome and others have been thinking about this problem and what updates they've been making to performance tools to lower the friction for building great experiences on the web.
Debugging JS
React Summit 2023React Summit 2023
24 min
Debugging JS
Top Content
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.
pnpm – a Fast, Disk Space Efficient Package Manager for JavaScript
DevOps.js Conf 2022DevOps.js Conf 2022
31 min
pnpm – a Fast, Disk Space Efficient Package Manager for JavaScript
You will learn about one of the most popular package managers for JavaScript and its advantages over npm and Yarn.A brief history of JavaScript package managersThe isolated node_modules structure created pnpmWhat makes pnpm so fastWhat makes pnpm disk space efficientMonorepo supportManaging Node.js versions with pnpm
From Friction to Flow: Debugging With Chrome DevTools
JSNation 2024JSNation 2024
32 min
From Friction to Flow: Debugging With Chrome DevTools
Coding and debugging should flow, not fizzle! Let's see what's new and improved in Chrome DevTools to make your web development & debugging journey smooth sailing.
Rome, a Modern Toolchain!
JSNation 2023JSNation 2023
31 min
Rome, a Modern Toolchain!
Top Content
Modern JavaScript projects come in many shapes: websites, web applications, desktop apps, mobile apps, and more. For most of them, the common denominator is the technical debt that comes from settings up tools: bundlers, testing suite, code analysis, documentation, etc. I want to present you Rome, a toolchain that aims to be a all-in-one toolchain for the web, with one single tool you can maintain the health of all your projects!

Workshops on related topic

React Performance Debugging Masterclass
React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Top Content
Featured WorkshopFree
Ivan Akulov
Ivan Akulov
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React, TypeScript, and TDD
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
Paul Everitt
Paul Everitt
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React Performance Debugging
React Advanced Conference 2023React Advanced Conference 2023
148 min
React Performance Debugging
Workshop
Ivan Akulov
Ivan Akulov
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
The Clinic.js Workshop
JSNation 2022JSNation 2022
71 min
The Clinic.js Workshop
Workshop
Rafael Gonzaga
Rafael Gonzaga
Learn the ways of the clinic suite of tools, which help you detect performance issues in your Node.js applications. This workshop walks you through a number of examples, and the knowledge required to do benchmarking and debug I/O and Event Loop issues.
Solve 100% Of Your Errors: How to Root Cause Issues Faster With Session Replay
JSNation 2023JSNation 2023
44 min
Solve 100% Of Your Errors: How to Root Cause Issues Faster With Session Replay
WorkshopFree
Ryan Albrecht
Ryan Albrecht
You know that annoying bug? The one that doesn’t show up locally? And no matter how many times you try to recreate the environment you can’t reproduce it? You’ve gone through the breadcrumbs, read through the stack trace, and are now playing detective to piece together support tickets to make sure it’s real.
Join Sentry developer Ryan Albrecht in this talk to learn how developers can use Session Replay - a tool that provides video-like reproductions of user interactions - to identify, reproduce, and resolve errors and performance issues faster (without rolling your head on your keyboard).