Repository navigation
Debugging JavaScript
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.
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"]
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-adaptersof 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.
- 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.mapadded (Haxe manual). When the run configuration builds your project, a Debug launch adds-debugfor you; see Debug builds are made for you.
The debugger starts the browser you select in the run configuration, taken from the IDE's list of browsers.
- Open Settings | Tools | Web Browsers and Preview.
- Find your browser in the list, or add it. Its Family must be Chrome or Firefox, and its checkbox must be selected.
- Set Path to the full path of the browser's executable file. The list starts out with only a program name there,
such as
chromeorfirefox. 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 (inContents/MacOS), not the.appfolder.
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 18 or later. To run the debug adapter, the plugin uses the first Node.js it finds, in this order:
- The run configuration, when you select Override Node.js executable: and enter a path.
- NodeJS executable: in the Runtime Overrides group of Settings | Build, Execution, Deployment | Build Tools | Haxe.
- NodeJS executable: under Runtimes on the Haxe SDK's page in Project Structure | Platform Settings | SDKs.
-
nodeon yourPATH.
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 Limehtml5target) and choose Debug. The first time, this creates a configuration named after the build file, such asbuild.hxml (Browser). It builds the file before every launch, and its content directory is the folder of the compiled.jsfile. - 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.
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.
- Select the browser you want to debug with.
- 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.

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.
The option Serve content directory with the built-in http server decides what the browser opens.
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.htmlthat loads your script. The server answers the address with it, and it never lists a directory. - the compiled
.jsfile and its.js.mapsource 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.jssave 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.
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 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.
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 |
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.
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.
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.
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.
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.
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.
- 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.
| 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.
Getting started
Working with projects
- The Haxe Tool Window
- Build Files
- Targets and Sections
- Resolve Context
- Libraries and Haxelib
- Defines and Custom Targets
- Building and Running
- Run Configurations
- Tools
- Compilation Server
Debugging
Testing
Profiling
Editing code
- Code Completion
- Diagnostics and Inspections
- Refactoring and Navigation
- Formatting and Code Style
- Conditional Compilation
- Editor Extras
Reference