Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
ketamynx
committed
Jun 29, 2012
1 parent
53ab754
commit 68d7ad5
Showing
28 changed files
with
8,376 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
var file_exists = function(f){ try{ require('fs').lstatSync(f); return true; }catch(e){ return false; }}; | ||
var is_file = function(f){ try{ return require('fs').lstatSync(f).isFile(); }catch(e){ return false; } }; | ||
var file_get_contents = function(f,mode){return (!file_exists(f))? '' : require('fs').readFileSync(f, mode); }; | ||
var get_constr = function(v){ return(v===null)?"[object Null]":Object.prototype.toString.call(v); }; | ||
var jsencr = function(o){ var e = []; return JSON.stringify(o, function(k,v){ | ||
if(typeof(v)==='function') return v.toString(); | ||
if(typeof(v)!=='object' || v===null) return v; | ||
for(var i in e){ if(e[i]===v){ return "Circular"; }}; | ||
e.push(v); return v; | ||
}); }; | ||
|
||
|
||
var dbg = { | ||
|
||
// AVOIDS RUNNING TWICE | ||
isStarted: false, | ||
|
||
// SSE CONNECTIONS | ||
cons: [], | ||
|
||
// MIMES HANDLING | ||
mimes: { | ||
'html': 'text/html', | ||
'htm' : 'text/html', | ||
'txt' : 'text/plain', | ||
'js' : 'text/javascript', | ||
'ico' : 'image/vnd.microsoft.icon', | ||
'css' : 'text/css', | ||
'eot': 'application/vnd.bw-fontobject', | ||
'ttf': 'application/x-font-ttf', | ||
'woff':'font/opentype' | ||
}, | ||
|
||
// SEND EVENT | ||
queued: [], | ||
pendingBroadcast:0, | ||
broadcastLag: 500, | ||
broadcastSSE: function(t, a){ | ||
clearTimeout(dbg.pendingBroadcast); | ||
|
||
var data = { t:t, a:a }; | ||
dbg.queued.push(data); | ||
|
||
var sendFn = function(){ | ||
if(!dbg.cons.length) return dbg.pendingBroadcast = setTimeout(function(){ sendFn(); },dbg.broadcastLag); | ||
|
||
var data = jsencr(dbg.queued); | ||
dbg.queued = []; | ||
for(var i=0; i<dbg.cons.length; i++)(function(c){ | ||
process.nextTick(function(){ c.end(data); }); | ||
}(dbg.cons[i])); | ||
}; | ||
|
||
dbg.pendingBroadcast = setTimeout(function(){ sendFn(); },dbg.broadcastLag); | ||
}, | ||
|
||
// ERROR HANDLERS | ||
serve500: function(s, err){try{ | ||
console.warn(err); | ||
|
||
var ISE = 'Internal server error\r\n'+err+'\r\n'; | ||
s.writeHead(404, {'Content-type':'text/plain', 'Content-length':ISE.length}); | ||
s.end(ISE); | ||
|
||
}catch(e){ console.warn(e); }}, | ||
|
||
serve404: function(s){try{ | ||
var NF = 'Not found\r\n'; | ||
s.writeHead(404, {'Content-type':'text/plain', 'Content-length':NF.length}); | ||
s.end(NF); | ||
|
||
}catch(e){ dbg.serve500(s,e); }}, | ||
|
||
// GET LOCAL FILENAME | ||
getlocalfn: function(path){ | ||
var p = require('path').normalize(__dirname + "/" + path); | ||
return p; | ||
}, | ||
|
||
// STATIC RESOURCES | ||
servestatic: function(q,s){ try{ | ||
var path = require('url').parse(q.url).pathname; | ||
if(path.charAt(0)==='/') path = path.substr(1); | ||
path = path.replace(/[\.]+(\/|\\)/gmi, ''); | ||
|
||
switch(path){ | ||
case "": | ||
case " ": | ||
case "index.html" : | ||
case "index.htm" : | ||
var fn = dbg.getlocalfn('./index.html'); | ||
var c = file_get_contents(fn,'utf-8'); | ||
|
||
s.writeHead(200, {'Content-type': dbg.mimes['html'], 'Content-length': c.length}); | ||
s.end(c); | ||
break; | ||
|
||
case 'images/favicon.ico': | ||
var icon = file_get_contents(dbg.getlocalfn('./images/favicon.ico')); | ||
s.writeHead(200, {'Content-type': dbg.mimes['ico'], 'Content-length': icon.length}); | ||
s.end(icon); | ||
break; | ||
|
||
case 'sse': | ||
|
||
var thiscon = dbg.cons.push(s); | ||
q.on('end', function(){ process.nextTick(function(){ | ||
s.writeHead(200,{ | ||
'Content-type':'text/event-stream', | ||
'Connection':'keep-alive', | ||
'Cache-Control': 'no-cache' | ||
}); | ||
}); }); | ||
|
||
q.on('close', function(){ dbg.cons.splice(thiscon,1);}); | ||
s.socket.setTimeout(0); | ||
|
||
break; | ||
|
||
default: | ||
var fn = dbg.getlocalfn('./'+path); | ||
if(!file_exists(fn)) return dbg.serve404(s); | ||
|
||
var c = file_get_contents(fn); | ||
var hdrs = {'Content-length': c.length}; | ||
var ext = fn.split('.').pop(); | ||
|
||
if(typeof(dbg.mimes[ext])==='string') hdrs['Content-type'] = dbg.mimes[ext]; | ||
|
||
s.writeHead(200, hdrs); | ||
s.end(c); | ||
break; | ||
} | ||
|
||
}catch(e){ dbg.serve500(s,e); }}, | ||
|
||
// EXECUTE COMMANDS | ||
execute: function(q,s){ | ||
var b = ''; | ||
q.on('data', function(c){ b+=c; }); | ||
q.on('end', function(){ | ||
b = require('querystring').parse(b); | ||
if(typeof(b.command)==='string'){ | ||
var r = {error:false}; | ||
|
||
try{ | ||
r.cnt = eval(b.command); | ||
r.type = (typeof(r.cnt)==='object' && r.cnt!==null) ? get_constr(r.cnt) : typeof(r.cnt); | ||
}catch(e){ r.error=e.toString(); } | ||
|
||
s.end(jsencr(r)); | ||
} else if(typeof(b.getsug)==='string'){ | ||
|
||
try{ var r = jsencr(dbg.getsug(JSON.parse(b.getsug))); } | ||
catch(e){ var r = "[]"; } | ||
|
||
s.writeHead(200, {'Content-type': dbg.mimes['txt'], 'Content-length': r.length}); | ||
s.end(r); | ||
}else{ | ||
return dbg.serve500(s,'Command was not found'); | ||
} | ||
}); | ||
}, | ||
|
||
// STD. REQUEST HANDLER LOGIC | ||
handle: function(q,s){ | ||
if(typeof(q.method)!=='string' || (q.method!=='GET' && q.method!=='POST')) | ||
return dbg.serve404(s); | ||
|
||
return (q.method==='GET') ? dbg.servestatic(q,s) : dbg.execute(q,s); | ||
}, | ||
|
||
// GET SUGGESTIONS | ||
getsug: function(o){ | ||
var r = []; | ||
if(typeof(o)!=='object' || !o.length || o.length!=2) return r; | ||
if(typeof(o[0])!=='string' || o[0]===''){ | ||
if(typeof(module)=='object') for(var i in module){ | ||
if(o[1]===''){ r.push(i); continue; }; | ||
if(i.split(o[1])[0]==='') r.push(i); | ||
} | ||
|
||
for(var i in global){ | ||
if(o[1]===''){ r.push(i); continue; }; | ||
if(i.split(o[1])[0]==='') r.push(i); | ||
} | ||
}else{try{ | ||
var tgt = eval(o[0]); if(typeof(tgt)!=='object') return r; | ||
for(var i in tgt){ | ||
if(o[1]===''){ r.push(i); continue; }; | ||
if(i.split(o[1])[0]==='') r.push(i); | ||
} | ||
}catch(e){ return r; }} | ||
return r; | ||
}, | ||
|
||
// WRAP CONSOLE.* API | ||
consolewrap: function(){ | ||
console.__log = console.log; | ||
console.log = function(){ console.__log.apply(console, arguments); dbg.broadcastSSE('log', arguments);}; | ||
|
||
console.__info = console.info; | ||
console.info = function(){ console.__info.apply(console, arguments); dbg.broadcastSSE('info', arguments);}; | ||
|
||
console.__warn = console.warn; | ||
console.warn = function(){ console.__warn.apply(console, arguments); dbg.broadcastSSE('warn', arguments);}; | ||
|
||
console.__error = console.error; | ||
console.error = function(){ console.__error.apply(console, arguments); dbg.broadcastSSE('error', arguments);}; | ||
|
||
process.on('uncaughtException', function (e) {console.error.call(console, e.toString()); }); | ||
|
||
}, | ||
|
||
// LOCAL DEBUGGER SERVER | ||
start: function(port, host, cb){ | ||
|
||
cb = typeof(cb)==='function' ? cb : function(){}; | ||
if(dbg.isStarted) return cb.call(null,false); | ||
|
||
var http = require('http'); | ||
dbg.sv = http.createServer(dbg.handle); | ||
|
||
dbg.sv.listen(port||55281, host||null,function(){ | ||
var add=dbg.sv.address(); | ||
console.log('Debugger server started at: ' + add.address + ':' + add.port); | ||
cb.call(null,dbg); | ||
}); | ||
|
||
dbg.sv.on('error', function(e){ | ||
console.warn('Failed to start debugger server. Error: '+e); | ||
}); | ||
|
||
dbg.consolewrap(); | ||
process.on('exit', function(){ try{dbg.sv.close();}catch(e){}; }); | ||
} | ||
|
||
}; | ||
|
||
dbg.start(); |
Oops, something went wrong.