Search code examples
javascriptnode.jsdebuggingvisual-studio-codeencapsulation

How can I debug private class fields in Node.js with VS Code?


How do I check the contents of the private fields of a class instance during runtime, debugging a Node app in VS Code?

It should be something basic but somehow seems not to be possible...

If not possible, which are the workarounds?

I'm using:

  • Node 15.3.0
  • VS Code 1.51.1

Solution

  • Update:

    VS Code's built-in javascript debugger did not support debugging of private class fields at the time of this question. It does now, since version 1.56.0 (April 2021).


    Old answer:

    VS Code's built-in javascript debugger (ms-vscode.js-debug) does not support private class fields yet. (there's a feature request for it on github)

    However, v8 does have a (currently in experimental state) method for reading private class fields. I've made a proof of concept project (leonardoraele/private-field-inspect) that uses Node's inspector API to programatically open a debug session at runtime to read the contents of the variable. (this does not interrupt the runtime execution)

    It works, but with a few caveats.

    Usage:

    import inspect from '../path/to/private-field-inspect';
    
    class Subject
    {
        publicValue = 'not so secret';
        #secretValue = 'my secret';
    }
    
    const subject = new Subject();
    
    inspect(subject)
        .then(console.debug);
    

    Output:

    { publicValue: 'not so secret', '#secretValue': 'my secret' }
    

    The workaround above is not satisfactory for me, so I think it's better to avoid using private class fields if possible, until they are properly supported by debuggers. Instead, use Symbols to hide private variables.

    Example:

    // my-class.js (or .msj)
    const PRIVATE = {
        SECRET_VAL = Symbol('#secretVal');
    };
    
    export default class Subject {
        // ms-vscode.js-debug can read it, but other modules can't
        [PRIVATE.SECRET_VAL]: 'my secret';
    
        doSomething()
        {
            const secret = this[PRIVATE.SECRET_VAL];
            // ...
        }
    }