How do I provide source-level debugging for a lang

2019-07-30 17:29发布

问题:

I understand the concept of using source maps with JavaScript to make debugging easier with minified scripts, etc. What I don't get is how source-level debugging works like it does for TypeScript in Visual Studio (http://blogs.msdn.com/b/typescript/archive/2012/11/15/announcing-typescript-0-8-1.aspx).

For example, if I create my own language that compiles/translates to JavaScript, how do I interface with browsers to provide this kind of source-level debugging? Is there a standard protocol for this? How does Visual Studio do it?

Update

To clarify even more, let's say I invent a language called Caffeinated Beverage Script that compiles to JavaScript. I build an IDE for my language and I want to be able to set breakpoints, step through code, inspect variables, etc. in my IDE while the JavaScript runs in a browser. How do I get my IDE to communicate with the browser on this level?

回答1:

You might consider WebKit's remote debugging API:

https://developers.google.com/chrome-developer-tools/docs/protocol/1.0/index

I believe that's what Sublime Web Inspector uses.

https://github.com/sokolovstas/SublimeWebInspector



回答2:

This is admittedly a bad answer, but I figure its better than nothing. If I were in your shoes, here is what I would do:

Now its obviously possible to communicate from the browser to the IDE using some kind of plugin, but I don't like that for at least 2 reasons: I don't enjoy coding in strongly-typed languages, and any code I produce will be inherently browser-specific. Although its not the lightest weight solution, XHR in blocking mode can get the job done.

The IDE would host a http server that sends the CORS header. The compiled source would contain something like this:

var ___, __INTERRUPT_SIGNAL = {};

(function() {
  var oXhr = new XMLHttpRequest();

  oXhr.open('POST', 'http://localhost/debugging_port', false); // Force XHR to work synchronously

  ___ = function(nLineNumber) {
    var sState = 'line_number='+nLineNumber;

    for(var nOffset = 0; nOffset < arguments.length; nOffset++) sState += '&i=' + escape(arguments[nOffset]);

    oXhr.send(sState);

    if(oXhr.status !== 200) return ___.apply(this, arguments); 
    var sCommand = oXhr.responseText;

    if(sCommand === 'step_into') {
      return;  
    }else if(sCommand === 'step_out') {
      throw __INTERRUPT_SIGNAL;
    }else{
      return ___.apply(this, arguments);
    }   
  };
})();

Now when the Caffeinated Beverage Script compiler compiles the source, it should place calls to the _ function at every line break of the source. For example,

int nCheese = 0;
char cLetter = 'Q';
customClass productZeroQ = nCheese * cLetter;

might compile to something like

var $0xA1, $0xA2, $0xA3;
___(9, $0xA1, $0xA2, $0xA3);
$0xA1 = 0;
___(10, $0xA1, $0xA2, $0xA3);
$0xA2 = 'Q';
___(11, $0xA1, $0xA2, $0xA3);
try {
  $0xA3 = $0x34.$0x21($0xA1, $0xA2);
}catch(oSignal){
  if(oSignal !== ___INTERRUPT_SIGNAL) throw oSignal;
}

XHR will block execution while the IDE decides to whether to step_out or step_forward. This could be extended to include the stack tracing, but I don't feel like writing a novel.

I know it's ugly, but I hope this helps a bit!