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?
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
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!