Vladislav Vlasov, a software engineer at Developer Soft and a teacher of Netology , wrote a series of articles on EcmaScript6 for his blog, in the first part of which he reviewed using examples of dynamic code analysis in EcmaScript using Iroh.js.Static and dynamic code analysis
Code analysis tools are a useful tool for detecting and detecting errors and features in code operation. Code analysis is static and dynamic. In the first case, the source code is parsed and analyzed without its execution, in the second, execution takes place in a controlled sandboxing environment (sandboxing), which provides meta information about the elements of the application during its execution.

')
In EcmaScript, which has
duck typing (duck-typing), static analysis tools are often used to detect potentially dangerous situations in the code without executing: inconsistencies between the types and arguments passed, incorrect operations with variables of inconsistent types, non-executable code sections, and so on. The most popular solutions are
Typescript and
Flow , based on the extension of the language with a special syntax.
Unlike programming languages, in which a strict type system is an integral part of them, and, accordingly, descriptions of types of variables and objects are already incorporated in the source code, EcmaScript, on the contrary, requires a manual description, moreover, dependent and different for individual static typing tools. This entails the
following disadvantages :
- the static typing tool introduces a set of synthetic instructions into the language, so the source code must necessarily be processed with a transpiler (transpiler), such as a cable with the appropriate plug-ins, or a TypeScript compiler, respectively;
- EcmaScript is dynamic in nature, and in many cases static typing is simply not applicable: for any objects received from the external environment, the data type will be string or any.
Iroh.js - solution for dynamic analysis of EcmaScript applications
The solution that eliminates the above disadvantages is the
Iroh.js EcmaScript code dynamic analyzer . Iroh.js allows you to perform code analysis and manipulation during execution, without having to modify the source code or annotate it, as is the case with static typing tools.
Iroh.js allows you to record the execution scheme of the code in real time, get information about the state of objects and the call stack, as well as control the behavior of the program on the fly.
Iroh.js can be used to obtain information on the following aspects of the runtime: the function call tree, the actual data types of objects and variables, implicit conversions to an object, and the primitive type (boxing / unboxing), including conversions to a string.
Iroh.js functions due to preliminary correction of the code in such a way as to record the events taking place without changing the logic and scheme of the source program execution. This provides the ability to add listeners to follow up and respond to actions. Iroh.js allows not only to monitor the behavior of the code in the execution mode, but also to modify it, intercepting the call of certain functions, setting the overlapping value for variables and so on.
Iroh.js tracks the call stack only for the modified code and cannot provide meta information or modification on the fly for native runtime functions or imported library elements. As a rule, it is not necessary to analyze and modify the behavior of the library code, but if necessary it is also possible - the scope of Iroh.js is determined by the code that was added to the sandbox of Iroh.js execution by means of prior patching.
Iroh.js can be added to the node.js application as an
npm package , and launched directly in the
browser , which can be useful for dynamic analysis of small independent code fragments or creating demo examples.
Example 1. Analysis of the call graph for the function calculating Fibonacci numbers
As the simplest example, we can consider two implementations of the Fibonacci number calculation function — a naive version with a full recursive tree, and an optimized solution with memorability of previous results. The source code of the proposed functions is presented below:
function fibonacciNaive(n) { if(n <= 0) return 0; return fibonacciNaive(n - 1) + fibonacciNaive(n - 2); };
function fibonacciMemoized(n, x1 = 0, x2 = 1) { if(n <= 0) return x1; return fibonacciMemoized(n - 1, x2, x1 + x2); };
Now you can make a dynamic analysis of these functions. Of course, both implementations provide the correct result, but
fibonacciMemoized
runs much faster than
fibonacciNaive
, and also consumes less memory.
Obviously, the point is to save intermediate calculations and optimize tail recursion.
The execution flow
analyzer based on Iroh.js allows you to see this clearly:
The dynamic analyzer allows you to easily find out that in the first, non-optimal case, for calculating the 6th Fibonacci number, the number of recursive calls reaches 41, while in the second - only 7. With the number of the calculated number increasing, in the first case the growth of recursive calls will be exponential, and in the second - linear.
Although the task of calculating Fibonacci numbers is extremely simple, and the optimization presented is trivial and widely known, Iroh.js allows you to track the graph of function calls and find redundant or incorrect calls.
By displaying the actual values of the arguments and variables, the code can be debugged during execution without adding synthetic
console.log
instructions.
Example 2. Modifying objects and variables on the fly
In the process of analyzing the behavior of an application with potentially complex and non-linear logic, it may be necessary to track the moment when the value of a particular variable or object has changed, or, conversely, to initiate changes of the current value to a special one at a certain moment. All this can be done by means of Iroh.js.
As a simple example, consider the code of a web page that executes AJAX requests to several web resources, but for debugging purposes, it is necessary to intercept calls to some of them by replacing the URL address with a debugging stub. A simplified fragment of the source code might look like this:
const urlAddresses = ['ADDR1', 'ADDR2', 'ADDR3']; const resultPromise = Promise.all(urlAddresses.map(addr => fetch(addr).then(res => res.text()).catch(err => new Error(err)))); resultPromise.then(result => console.log(result))
Suppose you need to replace the
ADDR3
with
ADDR3-test
. Using Iroh.js, the corresponding operation can be performed as follows:
const stage = new Iroh.Stage(code); // code - const listener = stage.addListener(Iroh.CALL); const originalFetch = fetch; listener.on("before", function (e) { if (e.object === fetch) { e.call = function (url) { const targetUrl = url === 'ADDR3' ? 'ADDR3-test' : url; return originalFetch.call(null, [targetUrl].concat(arguments.slice(1))) }); } }); eval(stage.script);
Iroh.js allows you to analyze and intercept function calls and the allocation of variables, providing the possibility of modifying their values and behavior on the fly. More examples can be found
here .
findings
Iroh.js is a powerful and functional tool for dynamic code analysis in EcmaScript. This tool can be used both for code analysis, including constructing a call graph, displaying actual types and values in variables and objects, and for modifying code on the fly, including code corrections based on events.
Dynamic analysis is a rather complicated method, but for EcmaScript, taking into account duck typing, the presence of host objects and native functions that allow you to change the behavior of the code on the fly, this is the only way to analyze and debug the code during execution.
Iroh.js can also use code to create functional tests without having to pre-modify it to export values. Based on Iroh.js, you can
measure the performance of problem areas of the code and even implement an online IDE development environment with the possibility of
step-by-step debugging and time-traveling debug, that is, executing the code in the reverse order to search for expressions that were the source of error or incorrect calculations.
From the Editor
Courses "Netology" on the topic: