This post was written by Martin Entlicher and Oleg Šelajev.

In this post, we explore how to debug a polyglot JavaScript Node.js, Ruby, and R application using GraalVM and the Chrome Dev tools debugger.

GraalVM is an embeddable high-performance polyglot virtual machine that aims to run all programming languages very fast. It is a large and versatile project, and if you are interested in what else GraalVM can do for you, look at the “10 things GraalVM can do” blog post by Chris Seaton.

GraalVM plus Node.js and JavaScript

GraalVM includes an ECMAScript compliant JavaScript engine, Graal.js, which can execute JavaScript code (duh!) on GraalVM.

After downloading GraalVM, you’ll find the js utility in the bin directory.

$ js

> 1 + 2

3

> print("Hello, polyglot world!")

Hello, polyglot world!

Besides running pure JavaScript, GraalVM can also run Node.js applications. The node in GraalVM relies on the native node implementation and replaces the JavaScript engine with its own.

So it can run node apps. If you start node with the —-jvm flag, your code will have access to the JDK classes out of the box.

$ node --jvm

> var BigInteger = Java.type(‘java.math.BigInteger’);

> console.log(BigInteger.valueOf(2).pow(100).toString(16));

10000000000000000000000000

On top of that, GraalVM comes with language agnostic tooling support, including debugger and profiler. Besides a debugger API, which is available for tool makers, GraalVM contains a backend implementation of the Chrome Inspector debugging protocol. That protocol, designed originally for JavaScript debugging, can be used to conveniently debug all GraalVM languages.

Demo polyglot application

To see GraalVM language debugging in action, open the demo application which uses three languages: JavaScript, Ruby, and R. Let’s suppose that you have a GraalVM installation at the GRAALVM_HOME directory. To run the demo app:

Clone the graalvm/graalvm-demos repository and navigate to the functionGraphDemo directory.

directory. run npm install to install the dependencies,

to install the dependencies, start the application: $GRAALVM_HOME/bin/node --polyglot --jvm --inspect server.js

It is a simple application that draws some graphs of various math functions. It uses JavaScript to handle the web communication, Ruby to verify the user input and R to parse the function and draw the function graph. Let’s use the debugger in Chrome developer tools to explore how it works.

Debugging in Chrome

To be able to attach Chrome dev tools to GraalVM, the launcher (e.g., the node executable) needs to run with the --inspect option, which can be followed by an optional host:port specification.

The --inspect option prints out a URL that is possible to paste into Chrome to attach the debugger. See Debugging Node.js with Google Chrome for instance, for the hints on how to use the Chrome client. When the debugger is attached, expand the file tree on the left side to explore the loaded scripts. You’ll see all node modules loaded under the node_modules folder and the main script server.js next to it. To intercept the web requests and start actual debugging, add a breakpoint to line 19, in the body of app.post() .

Open http://localhost:8088/ in another browser window and write log(x^2 + 1) to the function field. Press the “Draw Function” button and wait until the breakpoint is hit. Now you can use standard debugging actions to step through the application execution and tooltips to inspect the variable values.

You can see that from line 26 you can step into the Ruby code which does a primary verification of the function expression. It checks the input to prevent executing arbitrary code. When looking at the Call Stack, you can see a seamless transition from JavaScript to Ruby code. You can also navigate to all the frames on the stack, regardless of the particular language.

Now at line 28, step into the call to plotFunction call. This is R code that plots the function. Again, R data is available, together with the seamless call stack. All debugging features, including breakpoints, are available in all GraalVM languages.

On top of all that you can use the console to evaluate code written in the language of the current frame in focus.

Polyglot applications allow you to reuse the existing modules from any language ecosystem. Normally, it is a maintenance nightmare when you need to use different tooling to see what’s going on in the different components of the application you’re working on. With GraalVM’s language virtualization ability you can use one set of tools to debug all languages and libraries alike, without distracting yourself with the pesky details like what language a particular piece of code is written in.

Coverage Profiling in Chrome

If you want to take it to the next level, find the Coverage tab, which is located near the Console tab in the Chrome dev tools. Select it and click the record button to start capturing the coverage. Use the application a little, for example, having a function expression in the browser window, press the Draw Function button. The code that is used to fulfill the requests you make is marked in source scripts, including the node modules and other languages.

Conclusion

In this post, we looked at how GraalVM language virtualization ability allows you to debug polyglot applications. We used a small JavaScript, Ruby, and R web application that plots math functions you provide as input.

The ability to seamlessly debug through the different languages simplifies development of polyglot apps and allows for enhanced productivity by using the existing libraries from any programming languages ecosystems.

If you would like to implement your own language-agnostic tool for GraalVM, the best starting point is the getting started with instruments on GraalVM page.