Skip to content

Debugging JavaScript

m0rkeulv edited this page Oct 25, 2026 · 1 revision

Debug Haxe code compiled to JavaScript while it runs in a web browser or in Node.js. You set breakpoints in your .hx files; the source maps the compiler writes connect them to the generated JavaScript.

This page covers what is special about JavaScript. For the workflow all debuggers share, see Debugging Overview.

How it works

The IDE does not control the browser directly. It uses the open-source debug adapters that VS Code also uses. An adapter runs on Node.js, starts the browser and passes breakpoints, steps and values between the browser and the IDE.

flowchart LR
    ide["IntelliJ IDEA"] <-->|"Debug Adapter Protocol"| adapter["Debug adapter<br/>on Node.js"]
    adapter <--> target["Browser, or your<br/>Node.js program"]
Loading

The adapters speak the Debug Adapter Protocol (DAP). Which adapter you need depends on the browser:

Browser Debug adapter, as the run configuration names it Project
Chromium family: Google Chrome, Chromium, Microsoft Edge or another browser listed with the Chrome family; also Node.js programs js-debug adapter (Chromium, Node.js) 1.117.0 vscode-js-debug (MIT license), from its GitHub releases
Firefox Firefox DAP adapter 2.15.0 vscode-firefox-debug (MIT license), from Open VSX

Safari, Internet Explorer and other browsers cannot be debugged.

The adapters are not part of the plugin. You download each one once, from the run configuration:

  • Nothing is downloaded until you click Download. A debug session never downloads anything. The download uses the IDE's HTTP proxy settings.
  • The plugin downloads one fixed version of each adapter and checks its SHA-256 checksum before unpacking anything. A file that does not match is refused.
  • The adapters are stored in the folder haxe/debug-adapters of the IDE's system directory and are shared by all projects. Each IDE version has its own system directory, so after upgrading to a new IDE version you download them again.

Requirements

  • Node.js 18 or later, from nodejs.org. The debug adapters run on it. Running a page without the debugger does not need it.
  • Firefox or a Chromium-family browser, registered in the IDE with the full path of its executable.
  • The debug adapter for that browser, downloaded from the run configuration.
  • Source maps. Compile with -debug: Haxe then writes a source map next to the JavaScript file, named like it with .map added (Haxe manual). When the run configuration builds your project, a Debug launch adds -debug for you; see Debug builds are made for you.

Set up

Register the browser

The debugger starts the browser you select in the run configuration, taken from the IDE's list of browsers.

  1. Open Settings | Tools | Web Browsers and Preview.
  2. Find your browser in the list, or add it. Its Family must be Chrome or Firefox, and its checkbox must be selected.
  3. Set Path to the full path of the browser's executable file. The list starts out with only a program name there, such as chrome or firefox. The Haxe Web Browser configuration needs the path of an existing file, for Run as well as for Debug. On macOS, enter the program file inside the application bundle (in Contents/MacOS), not the .app folder.

Warning

On Linux, a browser installed as a snap package cannot be debugged. Its sandbox cannot read the temporary browser profile the debug adapter prepares, and the launch fails with an empty error. Use a browser that is not installed as a snap.

Install Node.js

Install Node.js 18 or later. To run the debug adapter, the plugin uses the first Node.js it finds, in this order:

  1. The run configuration, when you select Override Node.js executable: and enter a path.
  2. NodeJS executable: in the Runtime Overrides group of Settings | Build, Execution, Deployment | Build Tools | Haxe.
  3. NodeJS executable: under Runtimes on the Haxe SDK's page in Project Structure | Platform Settings | SDKs.
  4. node on your PATH.

Create the run configuration

The Haxe Web Browser run configuration runs and debugs a page in a browser. Create it in one of two ways:

  • From the Haxe tool window. Right-click the Build & run entry of a build file that compiles to JavaScript (for example -js bin/main.js, or the Lime html5 target) and choose Debug. The first time, this creates a configuration named after the build file, such as build.hxml (Browser). It builds the file before every launch, and its content directory is the folder of the compiled .js file.
  • By hand. Open Run | Edit Configurations…, click +, choose Haxe and then Haxe Web Browser. To have it build your project first, add a Run Haxe action step under Before launch.

In the configuration, choose the browser in Browser:. Default means the first active browser in the list. See Run Configurations for every field.

Download the debug adapter

Below Browser:, the configuration shows the adapter the selected browser needs, for example js-debug adapter (Chromium, Node.js) 1.117.0 — followed by a Download link.

  1. Select the browser you want to debug with.
  2. Click Download. The line changes to js-debug adapter (Chromium, Node.js) 1.117.0 — downloading... and then to js-debug adapter (Chromium, Node.js) 1.117.0 — downloaded, with a folder icon that opens the adapter's folder.

Until the adapter is downloaded, the configuration shows the error js-debug adapter (Chromium, Node.js) 1.117.0 is not downloaded (or the same for the Firefox adapter) for Debug. If you start Debug anyway, the IDE opens the configuration, and you can click Download there. Run and Profile start without the adapter. If the download fails, the line shows Adapter download failed: and the reason, and the Download link comes back.

A Haxe Web Browser configuration with the Download link for the js-debug adapter and the not downloaded error

The adapter line with its Download link, and the error shown until the adapter is downloaded

Node.js programs and JavaScript unit tests need the js-debug adapter too. The Node.js Application configuration has the same Download link; a Haxe Web Browser configuration with a Chromium-family browser selected works as well.

Where the page comes from

The option Serve content directory with the built-in http server decides what the browser opens.

Served by the IDE

This is the default. The IDE serves the Content directory: at http://127.0.0.1:<port>/, on a free port it picks, and opens that address. Only your own computer can reach the server. The directory needs:

  • an index.html that loads your script. The server answers the address with it, and it never lists a directory.
  • the compiled .js file and its .js.map source map.
  • everything else the page loads, such as images and data files.

Haxe does not write an index.html for a -js build, so add one to the output folder yourself. The Lime html5 target creates its own. For example, with this build file:

-cp src
-main Main
-js bin/main.js

save this page as bin/index.html and use bin as the content directory:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>my-app</title>
</head>
<body>
  <script src="main.js"></script>
</body>
</html>

The server tells the browser not to cache anything, so a rebuilt script is always loaded fresh.

Note

Before the first build the content directory usually does not exist yet. The configuration then shows Content directory does not exist: ... as a warning and starts anyway, so its build step can create the folder.

Served by your own server

Clear the option and enter the page's address in URL:. Also set Content directory: to the local folder your server serves. The debugger uses it to map the served files back to your sources: without it, breakpoints in .hx files do not bind, and Chromium-family browsers require it.

Run and debug

  • Run serves the content directory and opens the page in the selected browser, or opens the URL. No debugger and no Node.js are involved. The console shows where the content is served, and the server keeps running until you click Stop.
  • Debug starts the debug adapter on Node.js, and the adapter starts its own browser window. It uses a separate, temporary browser profile, so your usual extensions, bookmarks and logins are not there. Stop ends the session.

During a debug session, the output of trace() and console.log() appears in the console of the Debug tool window. Lines starting with [adapter] come from the debug adapter itself. With Chromium-family browsers, lines starting with [js-debug] report web workers that start and stop.

What works

Breakpoints, stepping, the Frames view, Variables and Evaluate Expression work with both browser families. The differences:

Feature Chromium family Firefox
Breakpoints in code that runs while the page loads Hit on the first load Hit after one automatic reload, on a page the IDE serves (see below)
Web workers Shown as extra threads Shown as extra threads, with problems (see below)
Smart Step Into Yes No
Completion from the running page in Evaluate Expression Yes No
Profiling (IntelliJ IDEA Ultimate) Yes, see Profiling JavaScript No

Expressions run as JavaScript

Evaluate Expression, watches and breakpoint conditions are sent to the browser as you write them, and the browser runs them as JavaScript in the generated code. Names that exist only at run time are therefore not marked as errors. Write such expressions so that they are valid JavaScript; simple ones like count > 3 read the same in both languages.

Threads pause on their own

The page and each web worker are separate threads in the Frames view, and each one pauses on its own. When a breakpoint stops a worker, the page and the other workers keep running. Resume Program resumes every thread that is paused.

Exception breakpoints

Of the options of the exception breakpoints, caught and uncaught exceptions work in the browser. JavaScript has no separate kind of runtime error, so the option for critical errors stops at uncaught exceptions, too.

Load-time breakpoints in Firefox

Firefox cannot stop in the first load of a page. So when the IDE serves the page, it makes the page reload once by itself, about two seconds after it opens; the second load runs with your breakpoints in place. With your own server there is no automatic reload: reload the page in the browser to stop in code that runs while the page loads.

Web workers in Firefox

Worker debugging in Firefox is unreliable because of a problem in Firefox itself: when you inspect objects or evaluate expressions in a paused worker, Firefox may never answer, and that worker then stops responding to the debugger. The IDE gives up on such a request after a few seconds, so the other views stay usable.

A worker that is paused at a breakpoint when the automatic reload happens can stay behind in the thread list as an inactive thread.

For sessions with many workers, use a Chromium-family browser.

Node.js programs

A program for Node.js runs and debugs with the Node.js Application run configuration. An hxml file that compiles to JavaScript has a Build & run entry for it in the Haxe tool window, next to the browser one; see Building and Running. The first Run or Debug creates a configuration named like node.hxml (Node.js). See Run Configurations for its fields.

Debug starts the program with node --inspect-brk and attaches the js-debug adapter, which sets your breakpoints before the first line runs, so breakpoints in code that runs at startup are hit too. The program's output appears in the console once; the adapter's own messages are not shown. Expressions run as JavaScript, as in the browser.

This needs:

  • Node.js 18 or later, from the configuration's Executable:, Build Tools | Haxe, the Haxe SDK or the PATH;
  • the js-debug adapter, downloaded with the Download link in the configuration;
  • source maps: compile with -debug; Build & run adds it when you choose Debug.

Unit tests compiled to JavaScript are debugged the same way; see Debug tests. Lime and OpenFL html5 tests run in a browser instead; see Unit Tests. Node.js programs cannot be profiled yet.

Limitations

  • The debugger always starts its own browser. It cannot attach to a browser that is already running.
  • Only Firefox and Chromium-family browsers can be debugged.
  • On Linux, browsers installed as snap packages cannot be debugged.
  • Smart Step Into offers no choice when the call is the last statement of a function; it then steps in like Step Into.
  • Render Objects with toString() has no effect in JavaScript sessions.
  • Web workers in Firefox: see above.

If something goes wrong

Message What to do
... is not downloaded Click Download in the configuration. Only Debug needs the adapter.
... has no usable executable. Set its path under Settings | Tools | Web Browsers. Set the full path of the browser's executable in Settings | Tools | Web Browsers and Preview.
Debugging supports Firefox and Chromium-family browsers; ... is neither. Pick another browser. Choose Firefox or a Chromium-family browser.
Node.js was not found on PATH. ... Install Node.js, or set its path as described above.
The configured Node.js executable does not exist: ... Correct the Node.js path you set, as described above.
Node.js ... is too old for the debug adapters — install version 18 or newer Install a newer Node.js.
Content directory does not exist: ... Build the project once, or correct the folder.

If the session starts but breakpoints are not hit, check that the build was compiled with -debug, so that the .js.map file exists next to the script. With your own server, check that Content directory: is the folder the server serves.

Clone this wiki locally