Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don’t worry, you can still create the pull request.
  • 11 commits
  • 12 files changed
  • 0 commit comments
  • 4 contributors
Commits on Jul 08, 2010
Tester Fixed to work with modern version of node.js a9cb020
kriserickson Removed debug code. 02f0363
kriserickson Clean up the readme.. 47121f8
kriserickson Fixed console logging. 0a6dc4f
kriserickson Added group functionality... Better documentation, and icons for erro…
…rs, warnings, and info...
13510ca
kriserickson Removed unused code... 16cd7ba
Commits on Jul 12, 2010
kriserickson Added queues so that messages don't get lost when they are sent quick…
…ly. Still order coming from the ibug.js file is not guaranteed to be in sequence (it rarely is in sequence due to a race when sending all the messages to node.s), the next fix would be to have the server wait a certain amount of time for missing messages before sending them on)...
c312172
Commits on Aug 24, 2010
kriserickson Add the queue... af2585f
Commits on Jul 29, 2011
@dmose dmose Switch from using load events to DOMContentLoaded events so that logg…
…ing is available sooner
1b49218
@kriserickson kriserickson Merge pull request #1 from dmose/master
Switch from using load events to DOMContentLoaded events so that logging is available sooner.
f1d0826
Commits on Jul 03, 2013
@kriserickson kriserickson Update README.md 037f3d3
Showing with 1,001 additions and 965 deletions.
  1. +13 −6 README.md
  2. +0 −7 browser.html
  3. +0 −1 embed.html
  4. +128 −31 firebug.js
  5. +251 −246 fu.js
  6. +453 −418 ibug.js
  7. +0 −147 ibug.py
  8. +0 −27 phone.html
  9. +40 −0 queue.js
  10. +116 −75 server.js
  11. BIN static/favicon.ico
  12. +0 −7 test.html
View
19 README.md
@@ -1,9 +1,12 @@
+This whole project is deprecated, use [Weinre](http://people.apache.org/~pmuellr/weinre/docs/latest/)
+=====================================================================================================
+
ibug: Firebug for your (i)Phone
===============================
Debug JavaScript on your mobile device from the comfort of your desktop browser.
-Originally developed by Joe Hewitt: [Announcement](http://www.joehewitt.com/blog/firebug_for_iph.php) - [Subversion](http://fbug.googlecode.com/svn/trunk/ibug/)
+Originally developed by Joe Hewitt: - [Subversion](http://fbug.googlecode.com/svn/trunk/ibug/)
_This is rough around the edges._
@@ -15,15 +18,19 @@ Setup
* Download and install Node.js: http://nodejs.org/#download
* Run the server: `node server.js`.
- * You can specify host/port if you'd like: `node server.js example.com:80`.
+
+* You can specify host/port if you'd like: `node server.js example.com:8001`.
* Point a browser at the server, http://YOUR_IP:8001/. This is your **console**.
- * You can use 127.0.0.1 as YOUR_IP but this will not work on an actual device.
+
+* You can use 127.0.0.1 as YOUR_IP but this will not work on an actual device.
* Paste `<script type="application/x-javascript" src="http://YOUR_IP:8001/ibug.js"></script>` into the page you want to debug.
-* Open the page you want to debug in your browser. This is your **client**.
+* Open the page you want to debug in your phone browser. This is your **client**.
+
+* Type `alert('Hello world!')` in your console window, if your phone displays 'Hello World' you are in business...
-* Type `alert('Hello world!')` in your console window.
+* It will then act like a firebug console, you can examine variables by typing their name... To get a proper breakdown type console.dir(varName).
-* BAM.
+* The following console functions are supported: console.log, console.debug, console.info, console.warn, console.assert, console.dir, console.dirxml, console.group, console.groupEnd, console.time, console.timeEnd, console.onError, console.$ (shortcut for document.getElementById), console.$$ (shortcut for document.getElementsByTagName), console.command (default action)
View
7 browser.html
@@ -1,7 +0,0 @@
-<html>
-<body>
-<script type="text/javascript">
-function command(text) {
- parent.command(text);
-}
-</script>
View
1 embed.html
@@ -1 +0,0 @@
-<script type="application/x-javascript" src="http://%(hostName)s/ibug.js"></script>
View
159 firebug.js
@@ -13,9 +13,7 @@
timeMap = {},
clPrefix = ">>> ",
greeting = 'Paste this into the head of any HTML pages you want to debug:',
- codeToPaste = '<script type="application/x-javascript" src="http://' + host + '/ibug.js"></script>',
- // JOHN
- iframe,
+ codeToPaste = '<script type="application/x-javascript" src="http://' + host + '/ibug.js"></script>',
scriptCount = 0;
// ********************************************************************************************
@@ -32,44 +30,43 @@
commandLine.focus();
commandLine.select();
- logRow([greeting], "info");
- logRow([escapeHTML(codeToPaste)], "text");
+ logRow([greeting], "info", false);
+ logRow([escapeHTML(codeToPaste)], "text", false);
- // JOHN
- iframe = document.createElement("iframe");
- iframe.style.border = "none";
- document.body.appendChild(iframe);
+ // JOHN
listen();
}
// JOHN:
function listen() {
var script = document.createElement("script");
+ var head = document.getElementsByTagName("head")[0];
+
// Use scriptCount to avoid caching interfering with results.
script.src = "http://" + host + "/console?" + scriptCount++;
- script.onload = listen;
- iframe.contentDocument.body.appendChild(script);
- }
-
- function focusCommandLine() {
- toggleConsole(true);
- if (commandLine) {
- commandLine.focus();
- }
+ script.onload = function() {
+ if (head && script.parentNode)
+ {
+ head.removeChild(script);
+ }
+ listen();
+ };
+ head.insertBefore(script, head.firstChild);
}
+
function evalCommandLine() {
var text = commandLine.value;
commandLine.value = "";
- appendToHistory(text);
- logRow([clPrefix, text], "command");
+ appendToHistory(text, false);
+ logRow([clPrefix, text], "command", false);
sendCommand(text);
}
function sendCommand(text) {
- var message = escape(text).replace("+", "%2B");
+ var message = encodeURIComponent(text).replace("+", "%2B");
var request = new XMLHttpRequest();
// Hack: Hardcoded to a single message.
// Command length is limited to the max uri of the browser.
@@ -139,7 +136,8 @@
function logFormatted(objects, className) {
var html = [],
format = objects[0],
- objIndex = 0;
+ objIndex = 0,
+ object;
if (typeof(format) != "string") {
format = "";
@@ -150,17 +148,17 @@
for (var i = 0; i < parts.length; ++i) {
var part = parts[i];
if (part && typeof(part) == "object") {
- var object = objects[++objIndex];
+ object = objects[++objIndex];
part.appender(object, html);
} else {
appendText(part, html);
}
}
- for (var i = objIndex+1; i < objects.length; ++i) {
+ for (i = objIndex+1; i < objects.length; ++i) {
appendText(" ", html);
- var object = objects[i];
+ object = objects[i];
if (typeof(object) == "string") {
appendText(object, html);
} else {
@@ -168,7 +166,7 @@
}
}
- logRow(html, className);
+ logRow(html, className, false);
}
function writeRow(message, className) {
@@ -197,8 +195,8 @@
for (var m = reg.exec(format); m; m = reg.exec(format)) {
var type = m[8] ? m[8] : m[5];
- appender = type in appenderMap ? appenderMap[type] : appendObject;
- precision = m[3] ? parseInt(m[3], 10) : (m[4] == "." ? -1 : 0);
+ var appender = type in appenderMap ? appenderMap[type] : appendObject;
+ var precision = m[3] ? parseInt(m[3], 10) : (m[4] == "." ? -1 : 0);
parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
parts.push({appender: appender, precision: precision});
@@ -212,6 +210,103 @@
}
// ********************************************************************************************
+ function objectToString(object)
+ {
+ try
+ {
+ return object+"";
+ }
+ catch (exc)
+ {
+ return null;
+ }
+ }
+
+ function appendText(object, html)
+ {
+ html.push(escapeHTML(objectToString(object)));
+ }
+
+ function appendNull(object, html)
+ {
+ html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
+ }
+
+ function appendString(object, html)
+ {
+ html.push('<span class="objectBox-string">&quot;', escapeHTML(objectToString(object)),
+ '&quot;</span>');
+ }
+
+
+ function appendInteger(object, html)
+ {
+ html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+ }
+
+ function appendFloat(object, html)
+ {
+ html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+ }
+
+ function appendObject(object, html)
+ {
+ try
+ {
+ if (object == undefined)
+ appendNull("undefined", html);
+ else if (object == null)
+ appendNull("null", html);
+ else if (typeof object == "string")
+ appendString(object, html);
+ else if (typeof object == "number")
+ appendInteger(object, html);
+ else if (typeof object == "function")
+ appendFunction(object, html);
+ else if (object.nodeType == 1)
+ appendSelector(object, html);
+ else if (typeof object == "object")
+ appendObjectFormatted(object, html);
+ else
+ appendText(object, html);
+ }
+ catch (exc)
+ {
+ }
+ }
+
+ function appendObjectFormatted(object, html)
+ {
+ var text = objectToString(object);
+ var reObject = /\[object (.*?)\]/;
+
+ var m = reObject.exec(text);
+ html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>')
+ }
+
+
+ function appendSelector(object, html)
+ {
+ html.push('<span class="objectBox-selector">');
+
+ html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
+ if (object.id)
+ html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
+ if (object.className)
+ html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
+
+ html.push('</span>');
+ }
+
+
+ function appendFunction(object, html)
+ {
+ var reName = /function ?(.*?)\(/;
+ var m = reName.exec(objectToString(object));
+ var name = m ? m[1] : "function";
+ html.push('<span class="objectBox-function">', escapeHTML(name), '()</span>');
+ }
+
function addEvent(object, name, handler) {
if (document.all) {
@@ -252,7 +347,8 @@
return "&quot;";
}
return "?";
- };
+ }
+
return String(value).replace(/[<>&"']/g, replaceChars);
}
@@ -281,13 +377,14 @@
className = lines[0];
html = lines[1];
}
- logRow([html], className);
+ logRow([html], className, false);
};
window.clearConsole = function() {
consoleBody.innerHTML = "";
};
- init();
+ window.addEventListener("load", init, false);
+
})();
View
497 fu.js
@@ -1,5 +1,5 @@
var createServer = require("http").createServer;
-var process = require("posix");
+var process = require("fs");
var sys = require("sys");
var url = require("url");
var DEBUG = false;
@@ -9,277 +9,282 @@ var fu = exports;
var NOT_FOUND = "Not Found\n";
function notFound(req, res) {
- res.sendHeader(404, [ ["Content-Type", "text/plain"]
- , ["Content-Length", NOT_FOUND.length]
- ]);
- res.sendBody(NOT_FOUND);
- res.finish();
+ res.writeHead(404, [
+ ["Content-Type", "text/plain"]
+ ,
+ ["Content-Length", NOT_FOUND.length]
+ ]);
+ res.write(NOT_FOUND);
+ res.end();
}
var getMap = {};
fu.get = function (path, handler) {
- getMap[path] = handler;
+ getMap[path] = handler;
};
var server = createServer(function (req, res) {
- if (req.method === "GET" || req.method === "HEAD") {
- var handler = getMap[url.parse(req.url).pathname] || notFound;
+ if (req.method === "GET" || req.method === "HEAD") {
+ var handler = getMap[url.parse(req.url).pathname] || notFound;
- res.simpleScript = function (code, body) {
- res.sendHeader(code, [ ["Content-Type", "application/javascript"]
- , ["Content-Length", body.length]
- , ["Pragma", "no-cache"]
- ]);
- res.sendBody(body);
- res.finish();
- };
+ function output(res, type, code, body) {
+ res.writeHead(code, [
+ ["Content-Type", type]
+ ,
+ ["Content-Length", body.length]
+ ,
+ ["Pragma", "no-cache"]
+ ]);
+ res.write(body);
+ res.end();
+ }
- res.simpleText = function (code, body) {
- res.sendHeader(code, [ ["Content-Type", "text/plain"]
- , ["Content-Length", body.length]
- ]);
- res.sendBody(body);
- res.finish();
- };
+ res.simpleScript = function (code, body) {
+ output(res, "application/javascript", code, body);
+ };
- res.simpleJSON = function (code, obj) {
- var body = JSON.stringify(obj);
- res.sendHeader(code, [ ["Content-Type", "text/json"]
- , ["Content-Length", body.length]
- , ["Pragma", "no-cache"]
- ]);
- res.sendBody(body);
- res.finish();
- };
+ res.simpleText = function (code, body) {
+ output(res, "text/plain", code, body);
+ };
- handler(req, res);
- }
+ res.simpleJSON = function (code, obj) {
+ output(res, "text/json", code, JSON.stringify(obj));
+
+ };
+
+ handler(req, res);
+ }
});
fu.listen = function (port, host) {
- server.listen(port, host);
- sys.puts("Server at http://" + (host || "127.0.0.1") + ":" + port.toString() + "/");
+ server.listen(port, host);
+ sys.puts("Server at http://" + (host || "127.0.0.1") + ":" + port.toString() + "/");
};
-fu.close = function () { server.close(); };
+fu.close = function () {
+ server.end();
+};
-function extname (path) {
- var index = path.lastIndexOf(".");
- return index < 0 ? "" : path.substring(index);
+function extname(path) {
+ var index = path.lastIndexOf(".");
+ return index < 0 ? "" : path.substring(index);
}
fu.staticHandler = function (filename) {
- var body, headers;
- var content_type = fu.mime.lookupExtension(extname(filename));
- var encoding = (content_type.slice(0,4) === "text" ? "utf8" : "binary");
+ var body, headers;
+ var content_type = fu.mime.lookupExtension(extname(filename));
+ var encoding = (content_type.slice(0, 4) === "text" ? "utf8" : "binary");
- function loadResponseData(callback) {
- if (body && headers && !DEBUG) {
- callback();
- return;
- }
-
- //sys.puts("loading " + filename + "...");
- var promise = process.cat(filename, encoding);
+ function loadResponseData(callback) {
+ if (body && headers && !DEBUG) {
+ callback();
+ return;
+ }
- promise.addCallback(function (data) {
- body = data;
- headers = [ [ "Content-Type" , content_type ]
- , [ "Content-Length" , body.length ]
+ //sys.puts("loading " + filename + "...");
+ process.readFile(filename, encoding, function (err, data) {
+ if (err) {
+ sys.puts("Error loading " + filename);
+ }
+ else {
+ body = data;
+ headers = [
+ [ "Content-Type" , content_type ]
+ ,
+ [ "Content-Length" , body.length ]
];
-// if (!DEBUG)
-// headers.push(["Pragma", "no-cache"]);
-
- //sys.puts("static file " + filename + " loaded");
- callback();
- });
+ // if (!DEBUG)
+ // headers.push(["Pragma", "no-cache"]);
+
+ //sys.puts("static file " + filename + " loaded");
+ callback();
+ }
+ });
- promise.addErrback(function () {
- sys.puts("Error loading " + filename);
- });
- }
- return function (req, res) {
- loadResponseData(function () {
- res.sendHeader(200, headers);
- res.sendBody(body, encoding);
- res.finish();
- });
- }
+ }
+
+ return function (req, res) {
+ loadResponseData(function () {
+ res.writeHead(200, headers);
+ res.write(body, encoding);
+ res.end();
+ });
+ }
};
// stolen from jack- thanks
fu.mime = {
- // returns MIME type for extension, or fallback, or octet-steam
- lookupExtension : function(ext, fallback) {
- return fu.mime.TYPES[ext.toLowerCase()] || fallback || 'application/octet-stream';
- },
-
- // List of most common mime-types, stolen from Rack.
- TYPES : { ".3gp" : "video/3gpp"
- , ".a" : "application/octet-stream"
- , ".ai" : "application/postscript"
- , ".aif" : "audio/x-aiff"
- , ".aiff" : "audio/x-aiff"
- , ".asc" : "application/pgp-signature"
- , ".asf" : "video/x-ms-asf"
- , ".asm" : "text/x-asm"
- , ".asx" : "video/x-ms-asf"
- , ".atom" : "application/atom+xml"
- , ".au" : "audio/basic"
- , ".avi" : "video/x-msvideo"
- , ".bat" : "application/x-msdownload"
- , ".bin" : "application/octet-stream"
- , ".bmp" : "image/bmp"
- , ".bz2" : "application/x-bzip2"
- , ".c" : "text/x-c"
- , ".cab" : "application/vnd.ms-cab-compressed"
- , ".cc" : "text/x-c"
- , ".chm" : "application/vnd.ms-htmlhelp"
- , ".class" : "application/octet-stream"
- , ".com" : "application/x-msdownload"
- , ".conf" : "text/plain"
- , ".cpp" : "text/x-c"
- , ".crt" : "application/x-x509-ca-cert"
- , ".css" : "text/css"
- , ".csv" : "text/csv"
- , ".cxx" : "text/x-c"
- , ".deb" : "application/x-debian-package"
- , ".der" : "application/x-x509-ca-cert"
- , ".diff" : "text/x-diff"
- , ".djv" : "image/vnd.djvu"
- , ".djvu" : "image/vnd.djvu"
- , ".dll" : "application/x-msdownload"
- , ".dmg" : "application/octet-stream"
- , ".doc" : "application/msword"
- , ".dot" : "application/msword"
- , ".dtd" : "application/xml-dtd"
- , ".dvi" : "application/x-dvi"
- , ".ear" : "application/java-archive"
- , ".eml" : "message/rfc822"
- , ".eps" : "application/postscript"
- , ".exe" : "application/x-msdownload"
- , ".f" : "text/x-fortran"
- , ".f77" : "text/x-fortran"
- , ".f90" : "text/x-fortran"
- , ".flv" : "video/x-flv"
- , ".for" : "text/x-fortran"
- , ".gem" : "application/octet-stream"
- , ".gemspec" : "text/x-script.ruby"
- , ".gif" : "image/gif"
- , ".gz" : "application/x-gzip"
- , ".h" : "text/x-c"
- , ".hh" : "text/x-c"
- , ".htm" : "text/html"
- , ".html" : "text/html"
- , ".ico" : "image/vnd.microsoft.icon"
- , ".ics" : "text/calendar"
- , ".ifb" : "text/calendar"
- , ".iso" : "application/octet-stream"
- , ".jar" : "application/java-archive"
- , ".java" : "text/x-java-source"
- , ".jnlp" : "application/x-java-jnlp-file"
- , ".jpeg" : "image/jpeg"
- , ".jpg" : "image/jpeg"
- , ".js" : "application/javascript"
- , ".json" : "application/json"
- , ".log" : "text/plain"
- , ".m3u" : "audio/x-mpegurl"
- , ".m4v" : "video/mp4"
- , ".man" : "text/troff"
- , ".mathml" : "application/mathml+xml"
- , ".mbox" : "application/mbox"
- , ".mdoc" : "text/troff"
- , ".me" : "text/troff"
- , ".mid" : "audio/midi"
- , ".midi" : "audio/midi"
- , ".mime" : "message/rfc822"
- , ".mml" : "application/mathml+xml"
- , ".mng" : "video/x-mng"
- , ".mov" : "video/quicktime"
- , ".mp3" : "audio/mpeg"
- , ".mp4" : "video/mp4"
- , ".mp4v" : "video/mp4"
- , ".mpeg" : "video/mpeg"
- , ".mpg" : "video/mpeg"
- , ".ms" : "text/troff"
- , ".msi" : "application/x-msdownload"
- , ".odp" : "application/vnd.oasis.opendocument.presentation"
- , ".ods" : "application/vnd.oasis.opendocument.spreadsheet"
- , ".odt" : "application/vnd.oasis.opendocument.text"
- , ".ogg" : "application/ogg"
- , ".p" : "text/x-pascal"
- , ".pas" : "text/x-pascal"
- , ".pbm" : "image/x-portable-bitmap"
- , ".pdf" : "application/pdf"
- , ".pem" : "application/x-x509-ca-cert"
- , ".pgm" : "image/x-portable-graymap"
- , ".pgp" : "application/pgp-encrypted"
- , ".pkg" : "application/octet-stream"
- , ".pl" : "text/x-script.perl"
- , ".pm" : "text/x-script.perl-module"
- , ".png" : "image/png"
- , ".pnm" : "image/x-portable-anymap"
- , ".ppm" : "image/x-portable-pixmap"
- , ".pps" : "application/vnd.ms-powerpoint"
- , ".ppt" : "application/vnd.ms-powerpoint"
- , ".ps" : "application/postscript"
- , ".psd" : "image/vnd.adobe.photoshop"
- , ".py" : "text/x-script.python"
- , ".qt" : "video/quicktime"
- , ".ra" : "audio/x-pn-realaudio"
- , ".rake" : "text/x-script.ruby"
- , ".ram" : "audio/x-pn-realaudio"
- , ".rar" : "application/x-rar-compressed"
- , ".rb" : "text/x-script.ruby"
- , ".rdf" : "application/rdf+xml"
- , ".roff" : "text/troff"
- , ".rpm" : "application/x-redhat-package-manager"
- , ".rss" : "application/rss+xml"
- , ".rtf" : "application/rtf"
- , ".ru" : "text/x-script.ruby"
- , ".s" : "text/x-asm"
- , ".sgm" : "text/sgml"
- , ".sgml" : "text/sgml"
- , ".sh" : "application/x-sh"
- , ".sig" : "application/pgp-signature"
- , ".snd" : "audio/basic"
- , ".so" : "application/octet-stream"
- , ".svg" : "image/svg+xml"
- , ".svgz" : "image/svg+xml"
- , ".swf" : "application/x-shockwave-flash"
- , ".t" : "text/troff"
- , ".tar" : "application/x-tar"
- , ".tbz" : "application/x-bzip-compressed-tar"
- , ".tcl" : "application/x-tcl"
- , ".tex" : "application/x-tex"
- , ".texi" : "application/x-texinfo"
- , ".texinfo" : "application/x-texinfo"
- , ".text" : "text/plain"
- , ".tif" : "image/tiff"
- , ".tiff" : "image/tiff"
- , ".torrent" : "application/x-bittorrent"
- , ".tr" : "text/troff"
- , ".txt" : "text/plain"
- , ".vcf" : "text/x-vcard"
- , ".vcs" : "text/x-vcalendar"
- , ".vrml" : "model/vrml"
- , ".war" : "application/java-archive"
- , ".wav" : "audio/x-wav"
- , ".wma" : "audio/x-ms-wma"
- , ".wmv" : "video/x-ms-wmv"
- , ".wmx" : "video/x-ms-wmx"
- , ".wrl" : "model/vrml"
- , ".wsdl" : "application/wsdl+xml"
- , ".xbm" : "image/x-xbitmap"
- , ".xhtml" : "application/xhtml+xml"
- , ".xls" : "application/vnd.ms-excel"
- , ".xml" : "application/xml"
- , ".xpm" : "image/x-xpixmap"
- , ".xsl" : "application/xml"
- , ".xslt" : "application/xslt+xml"
- , ".yaml" : "text/yaml"
- , ".yml" : "text/yaml"
- , ".zip" : "application/zip"
- }
-};
+ // returns MIME type for extension, or fallback, or octet-steam
+ lookupExtension : function(ext, fallback) {
+ return fu.mime.TYPES[ext.toLowerCase()] || fallback || 'application/octet-stream';
+ },
+
+ // List of most common mime-types, stolen from Rack.
+ TYPES : { ".3gp" : "video/3gpp"
+ , ".a" : "application/octet-stream"
+ , ".ai" : "application/postscript"
+ , ".aif" : "audio/x-aiff"
+ , ".aiff" : "audio/x-aiff"
+ , ".asc" : "application/pgp-signature"
+ , ".asf" : "video/x-ms-asf"
+ , ".asm" : "text/x-asm"
+ , ".asx" : "video/x-ms-asf"
+ , ".atom" : "application/atom+xml"
+ , ".au" : "audio/basic"
+ , ".avi" : "video/x-msvideo"
+ , ".bat" : "application/x-msdownload"
+ , ".bin" : "application/octet-stream"
+ , ".bmp" : "image/bmp"
+ , ".bz2" : "application/x-bzip2"
+ , ".c" : "text/x-c"
+ , ".cab" : "application/vnd.ms-cab-compressed"
+ , ".cc" : "text/x-c"
+ , ".chm" : "application/vnd.ms-htmlhelp"
+ , ".class" : "application/octet-stream"
+ , ".com" : "application/x-msdownload"
+ , ".conf" : "text/plain"
+ , ".cpp" : "text/x-c"
+ , ".crt" : "application/x-x509-ca-cert"
+ , ".css" : "text/css"
+ , ".csv" : "text/csv"
+ , ".cxx" : "text/x-c"
+ , ".deb" : "application/x-debian-package"
+ , ".der" : "application/x-x509-ca-cert"
+ , ".diff" : "text/x-diff"
+ , ".djv" : "image/vnd.djvu"
+ , ".djvu" : "image/vnd.djvu"
+ , ".dll" : "application/x-msdownload"
+ , ".dmg" : "application/octet-stream"
+ , ".doc" : "application/msword"
+ , ".dot" : "application/msword"
+ , ".dtd" : "application/xml-dtd"
+ , ".dvi" : "application/x-dvi"
+ , ".ear" : "application/java-archive"
+ , ".eml" : "message/rfc822"
+ , ".eps" : "application/postscript"
+ , ".exe" : "application/x-msdownload"
+ , ".f" : "text/x-fortran"
+ , ".f77" : "text/x-fortran"
+ , ".f90" : "text/x-fortran"
+ , ".flv" : "video/x-flv"
+ , ".for" : "text/x-fortran"
+ , ".gem" : "application/octet-stream"
+ , ".gemspec" : "text/x-script.ruby"
+ , ".gif" : "image/gif"
+ , ".gz" : "application/x-gzip"
+ , ".h" : "text/x-c"
+ , ".hh" : "text/x-c"
+ , ".htm" : "text/html"
+ , ".html" : "text/html"
+ , ".ico" : "image/vnd.microsoft.icon"
+ , ".ics" : "text/calendar"
+ , ".ifb" : "text/calendar"
+ , ".iso" : "application/octet-stream"
+ , ".jar" : "application/java-archive"
+ , ".java" : "text/x-java-source"
+ , ".jnlp" : "application/x-java-jnlp-file"
+ , ".jpeg" : "image/jpeg"
+ , ".jpg" : "image/jpeg"
+ , ".js" : "application/javascript"
+ , ".json" : "application/json"
+ , ".log" : "text/plain"
+ , ".m3u" : "audio/x-mpegurl"
+ , ".m4v" : "video/mp4"
+ , ".man" : "text/troff"
+ , ".mathml" : "application/mathml+xml"
+ , ".mbox" : "application/mbox"
+ , ".mdoc" : "text/troff"
+ , ".me" : "text/troff"
+ , ".mid" : "audio/midi"
+ , ".midi" : "audio/midi"
+ , ".mime" : "message/rfc822"
+ , ".mml" : "application/mathml+xml"
+ , ".mng" : "video/x-mng"
+ , ".mov" : "video/quicktime"
+ , ".mp3" : "audio/mpeg"
+ , ".mp4" : "video/mp4"
+ , ".mp4v" : "video/mp4"
+ , ".mpeg" : "video/mpeg"
+ , ".mpg" : "video/mpeg"
+ , ".ms" : "text/troff"
+ , ".msi" : "application/x-msdownload"
+ , ".odp" : "application/vnd.oasis.opendocument.presentation"
+ , ".ods" : "application/vnd.oasis.opendocument.spreadsheet"
+ , ".odt" : "application/vnd.oasis.opendocument.text"
+ , ".ogg" : "application/ogg"
+ , ".p" : "text/x-pascal"
+ , ".pas" : "text/x-pascal"
+ , ".pbm" : "image/x-portable-bitmap"
+ , ".pdf" : "application/pdf"
+ , ".pem" : "application/x-x509-ca-cert"
+ , ".pgm" : "image/x-portable-graymap"
+ , ".pgp" : "application/pgp-encrypted"
+ , ".pkg" : "application/octet-stream"
+ , ".pl" : "text/x-script.perl"
+ , ".pm" : "text/x-script.perl-module"
+ , ".png" : "image/png"
+ , ".pnm" : "image/x-portable-anymap"
+ , ".ppm" : "image/x-portable-pixmap"
+ , ".pps" : "application/vnd.ms-powerpoint"
+ , ".ppt" : "application/vnd.ms-powerpoint"
+ , ".ps" : "application/postscript"
+ , ".psd" : "image/vnd.adobe.photoshop"
+ , ".py" : "text/x-script.python"
+ , ".qt" : "video/quicktime"
+ , ".ra" : "audio/x-pn-realaudio"
+ , ".rake" : "text/x-script.ruby"
+ , ".ram" : "audio/x-pn-realaudio"
+ , ".rar" : "application/x-rar-compressed"
+ , ".rb" : "text/x-script.ruby"
+ , ".rdf" : "application/rdf+xml"
+ , ".roff" : "text/troff"
+ , ".rpm" : "application/x-redhat-package-manager"
+ , ".rss" : "application/rss+xml"
+ , ".rtf" : "application/rtf"
+ , ".ru" : "text/x-script.ruby"
+ , ".s" : "text/x-asm"
+ , ".sgm" : "text/sgml"
+ , ".sgml" : "text/sgml"
+ , ".sh" : "application/x-sh"
+ , ".sig" : "application/pgp-signature"
+ , ".snd" : "audio/basic"
+ , ".so" : "application/octet-stream"
+ , ".svg" : "image/svg+xml"
+ , ".svgz" : "image/svg+xml"
+ , ".swf" : "application/x-shockwave-flash"
+ , ".t" : "text/troff"
+ , ".tar" : "application/x-tar"
+ , ".tbz" : "application/x-bzip-compressed-tar"
+ , ".tcl" : "application/x-tcl"
+ , ".tex" : "application/x-tex"
+ , ".texi" : "application/x-texinfo"
+ , ".texinfo" : "application/x-texinfo"
+ , ".text" : "text/plain"
+ , ".tif" : "image/tiff"
+ , ".tiff" : "image/tiff"
+ , ".torrent" : "application/x-bittorrent"
+ , ".tr" : "text/troff"
+ , ".txt" : "text/plain"
+ , ".vcf" : "text/x-vcard"
+ , ".vcs" : "text/x-vcalendar"
+ , ".vrml" : "model/vrml"
+ , ".war" : "application/java-archive"
+ , ".wav" : "audio/x-wav"
+ , ".wma" : "audio/x-ms-wma"
+ , ".wmv" : "video/x-ms-wmv"
+ , ".wmx" : "video/x-ms-wmx"
+ , ".wrl" : "model/vrml"
+ , ".wsdl" : "application/wsdl+xml"
+ , ".xbm" : "image/x-xbitmap"
+ , ".xhtml" : "application/xhtml+xml"
+ , ".xls" : "application/vnd.ms-excel"
+ , ".xml" : "application/xml"
+ , ".xpm" : "image/x-xpixmap"
+ , ".xsl" : "application/xml"
+ , ".xslt" : "application/xslt+xml"
+ , ".yaml" : "text/yaml"
+ , ".yml" : "text/yaml"
+ , ".zip" : "application/zip"
+ }
+};
View
871 ibug.js
@@ -1,468 +1,503 @@
+var _host;
+var messageNumber = 0;
+var scriptCount = 0;
-if (!("console" in window) || !("firebug" in console)) {
-(function() {
-
- // JOHN: Save a reference to the console for debugging ;)
- window._console = window.console;
-
- window.console = {
- firebug: "ibug0.1",
-
- log: function() {
- logFormatted(arguments, "");
- },
-
- debug: function() {
- logFormatted(arguments, "debug");
- },
-
- info: function() {
- logFormatted(arguments, "info");
- },
-
- warn: function() {
- logFormatted(arguments, "warning");
- },
-
- error: function() {
- logFormatted(arguments, "error");
- },
-
- assert: function(truth, message) {
- if (!truth) {
- var args = [];
- for (var i = 1; i < arguments.length; ++i)
- args.push(arguments[i]);
-
- logFormatted(args.length ? args : ["Assertion Failure"], "error");
- throw message ? message : "Assertion Failure";
- }
- },
-
- dir: function(object) {
- var html = [],
- pairs = [];
-
- for (var name in object) {
- try {
- pairs.push([name, object[name]]);
- } catch (exc) { }
- }
-
- pairs.sort(function(a, b) { return a[0] < b[0] ? -1 : 1; });
-
- html.push('<table>');
- for (var i = 0; i < pairs.length; ++i) {
- var name = pairs[i][0], value = pairs[i][1];
-
- html.push('<tr>',
- '<td class="propertyNameCell"><span class="propertyName">',
- escapeHTML(name), '</span></td>', '<td><span class="propertyValue">');
- appendObject(value, html);
- html.push('</span></td></tr>');
- }
- html.push('</table>');
-
- logRow(html, "dir");
- },
-
- dirxml: function(node) {
- var html = [];
-
- appendNode(node, html);
- logRow(html, "dirxml");
- },
-
- group: function() {
- logRow(arguments, "group", pushGroup);
- },
-
- groupEnd: function() {
- logRow(arguments, "", popGroup);
- },
-
- time: function(name) {
- timeMap[name] = (new Date()).getTime();
- },
-
- timeEnd: function(name) {
- if (name in timeMap) {
- var delta = (new Date()).getTime() - timeMap[name];
- logFormatted([name+ ":", delta+"ms"]);
- delete timeMap[name];
+function Queue() {
+
+ var queue = [];
+
+ var queueSpace = 0;
+
+ this.Count = function() {
+ return queue.length - queueSpace;
+ }
+
+ this.IsEmpty = function() {
+
+ // return true if the queue is empty, and false otherwise
+ return (queue.length == 0);
+
+ }
+
+ this.Enqueue = function(element) {
+ queue.push(element);
+ }
+
+ this.Dequeue = function() {
+
+ var element = undefined;
+
+ if (queue.length) {
+
+ element = queue[queueSpace];
+
+ if (++queueSpace * 2 >= queue.length) {
+ queue = queue.slice(queueSpace);
+ queueSpace = 0;
}
- },
-
- count: function() {
- this.warn(["count() not supported."]);
- },
-
- trace: function() {
- this.warn(["trace() not supported."]);
- },
-
- profile: function() {
- this.warn(["profile() not supported."]);
- },
-
- profileEnd: function() { },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- $: function(id) {
- return document.getElementById(id);
- },
-
- $$: function(selector) {
- // XXXjoe Make this into getElementsBySelector
- return document.getElementsByTagName(selector);
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- onError: function(msg, href, lineNo) {
- var html = [],
- lastSlash = href.lastIndexOf("/"),
- fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
-
- html.push(
- '<span class="errorMessage">', msg, '</span>',
- '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
- );
-
- logRow(html, "error");
- },
-
- command: function(text) {
- with (console) {
- try {
- var result = eval(text);
- console.log(result);
+ }
+
+ return element;
+ }
+}
+
+if (!("console" in window) || !("firebug" in console)) {
+ (function() {
+
+ // JOHN: Save a reference to the console for debugging ;)
+ window._console = window.console;
+
+ window.console = {
+ firebug: "ibug0.1",
+
+ log: function() {
+ logFormatted(arguments, "");
+ },
+
+ debug: function() {
+ logFormatted(arguments, "debug");
+ },
+
+ info: function() {
+ logFormatted(arguments, "info");
+ },
+
+ warn: function() {
+ logFormatted(arguments, "warning");
+ },
+
+ error: function() {
+ logFormatted(arguments, "error");
+ },
+
+ assert: function(truth, message) {
+ if (!truth) {
+ var args = [];
+ for (var i = 1; i < arguments.length; ++i)
+ args.push(arguments[i]);
+
+ logFormatted(args.length ? args : ["Assertion Failure"], "error");
+ throw message ? message : "Assertion Failure";
}
- catch (exc) {
- console.onError(exc.message, exc.sourceId+"", exc.line);
+ },
+
+ dir: function(object) {
+ var html = [],
+ pairs = [],
+ name, value;
+
+ for (name in object) {
+ try {
+ pairs.push([name, object[name]]);
+ } catch (exc) {
+ }
+ }
+
+ pairs.sort(function(a, b) {
+ return a[0] < b[0] ? -1 : 1;
+ });
+
+ html.push('<table>');
+ for (var i = 0; i < pairs.length; ++i) {
+ name = pairs[i][0];
+ value = pairs[i][1];
+
+ html.push('<tr>',
+ '<td class="propertyNameCell"><span class="propertyName">',
+ escapeHTML(name), '</span></td>', '<td><span class="propertyValue">');
+ appendObject(value, html);
+ html.push('</span></td></tr>');
+ }
+ html.push('</table>');
+
+ logRow(html, "dir");
+ },
+
+ dirxml: function(node) {
+ var html = [];
+
+ appendNode(node, html);
+ logRow(html, "dirxml");
+ },
+
+ group: function() {
+ logRow(arguments, "group");
+ },
+
+ groupEnd: function() {
+ logRow(arguments, "");
+ },
+
+ time: function(name) {
+ timeMap[name] = (new Date()).getTime();
+ },
+
+ timeEnd: function(name) {
+ if (name in timeMap) {
+ var delta = (new Date()).getTime() - timeMap[name];
+ logFormatted([name + ":", delta + "ms"], false);
+ delete timeMap[name];
+ }
+ },
+
+ count: function() {
+ this.warn(["count() not supported."]);
+ },
+
+ trace: function() {
+ this.warn(["trace() not supported."]);
+ },
+
+ profile: function() {
+ this.warn(["profile() not supported."]);
+ },
+
+ profileEnd: function() {
+ },
+
+ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+ $: function(id) {
+ return document.getElementById(id);
+ },
+
+ $$: function(selector) {
+ return document.getElementsByTagName(selector);
+ },
+
+ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+ onError: function(msg, href, lineNo) {
+ var html = [],
+ lastSlash = href.lastIndexOf("/"),
+ fileName = lastSlash == -1 ? href : href.substr(lastSlash + 1);
+
+ html.push(
+ '<span class="errorMessage">', msg, '</span>',
+ '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
+ );
+
+ logRow(html, "error");
+ },
+
+ command: function(text) {
+ with (console) {
+ try {
+ var result = eval(text);
+ console.log(result);
+ }
+ catch (exc) {
+ console.onError(exc.message, exc.location, exc.lineNumber);
+ }
}
}
- }
- };
-
-
- // ********************************************************************************************
-
- var timeMap = {},
- queue = [],
- scriptCount = 0,
- iframe,
- host;
-
- function init() {
- // Hack: Figure out what the correct host is.
- var scripts = document.getElementsByTagName("script");
- for (var i = 0; i < scripts.length; i++) {
- var script = scripts[i];
- if (/ibug\.js/.test(script.src)) {
- host = script.src.split("/")[2];
+ };
+
+
+ // ********************************************************************************************
+
+ var timeMap = {},
+ queue = new Queue();
+
+ function init() {
+ // Hack: Figure out what the correct host is.
+ var scripts = document.getElementsByTagName("script");
+ for (var i = 0; i < scripts.length; i++) {
+ var script = scripts[i];
+ if (/ibug\.js/.test(script.src)) {
+ _host = script.src.split("/")[2];
+ break;
+ }
}
+
}
-
- iframe = document.createElement("iframe");
- document.body.appendChild(iframe);
- iframe.style.display = "none";
- listen();
- }
-
- var onload = (function(){
- // Detect whether script.onload is supported.
- // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
- var testScript = document.createElement("script");
- testScript.setAttribute("onload", "return");
- if (typeof testScript.onload == "function") {
- return function(script, callback) {
- var loaded = false;
- script.onload = script.onreadystatechange = function(){
- var state = this.readyState;
- if (!loaded && (!state || state == 'loaded' || state == 'complete')) {
- loaded = true;
- callback();
- }
+
+
+ function listen() {
+ var script = document.createElement("script");
+ script.src = "http://" + _host + "/client?s=" + scriptCount++;
+
+ var head = document.getElementsByTagName("head")[0];
+
+ script.onDOMContentLoaded = function() {
+ if (head && script.parentNode)
+ {
+ head.removeChild(script);
}
- }
- } else {
- // If script.onload is not supported use polling with a counter
- // to detect whether the script is loaded.
- // http://remysharp.com/2007/04/12/how-to-detect-when-an-external-library-has-loaded/
- window.console.lastScriptLoaded = -1;
- return function(script, callback) {
- var callbackTimer = setInterval(function(){
- if (window.console.lastScriptLoaded == scriptCount - 1){
- clearInterval(callbackTimer);
- callback();
+ listen();
+ };
+ head.insertBefore(script, head.firstChild);
+
+ }
+
+ var maximumLineLength = 1500;
+
+
+ function sendMessage(message) {
+ queue.Enqueue(message);
+ setTimeout(dequeMessages, 200);
+ }
+
+ function dequeMessages()
+ {
+ if (!queue.IsEmpty())
+ {
+
+ // Messages are broken into bits to avoid browser uri length limits.
+ // n = message number
+ // l = number of bits in this message
+ // b = current bit
+ // m = bit message
+ var message = encodeURIComponent(queue.Dequeue());
+ var bitLength = Math.ceil(message.length / maximumLineLength);
+ var bitNumber = 0;
+
+ if (typeof(_host) != "undefined") {
+ var request = new XMLHttpRequest();
+ for (var i = 0; i < message.length; i += maximumLineLength) {
+
+ // Command length is limited to the max uri of the browser.
+ request.open("GET", "http://" + _host + "/response?" + "n=" + messageNumber +
+ "&l=" + bitLength + "&b=" + bitNumber++ + "&m=" + message.substring(i, i + maximumLineLength), true);
+ request.send(null);
}
- }, 100);
+ messageNumber++;
+ }
+
}
+ setTimeout(dequeMessages, 200);
}
- })();
-
- function listen(){
- var script = document.createElement("script");
- script.src = "http://" + host + "/client?s=" + scriptCount++;
-
- onload(script, listen);
-
- // TODO: What about onerror?
- // script.onerror = listen;
- // TODO: Throws on the Pre - what's going wrong?
- // TODO: Is there a point to putting the script in an iframe?
- try {
- iframe.contentDocument.body.appendChild(script);
- } catch (err) {
- window.document.body.appendChild(script);
- }
- }
-
- // TODO: Cleanup!
- var MAX_BIT_LENGTH = 1500;
- var messageNumber = 0;
-
- function sendMessage(message) {
- // Messages are broken into bits to avoid browser uri length limits.
- // n = message number
- // l = number of bits in this message
- // b = current bit
- // m = bit message
- var message = escape(message);
- var bitLength = Math.ceil(message.length / MAX_BIT_LENGTH);
- var bitNumber = 0;
-
- for (var i = 0, step = MAX_BIT_LENGTH; i < message.length; i = i + step) {
- var src = "http://" + host + "/response?"
- src += "n=" + messageNumber;
- src += "&l=" + bitLength;
- src += "&b=" + bitNumber++;
- src += "&m=" + message.substring(i, i + step);
- new Image().src = src;
+
+ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+ function appendText(object, html) {
+ html.push(escapeHTML(objectToString(object)));
}
-
- messageNumber++;
- }
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- function appendText(object, html) {
- html.push(escapeHTML(objectToString(object)));
- }
- function appendNull(object, html) {
- html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
- }
+ function appendNull(object, html) {
+ html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
+ }
- function appendString(object, html) {
- html.push('<span class="objectBox-string">&quot;', escapeHTML(objectToString(object)),
- '&quot;</span>');
- }
+ function appendString(object, html) {
+ html.push('<span class="objectBox-string">&quot;', escapeHTML(objectToString(object)),
+ '&quot;</span>');
+ }
- function appendInteger(object, html) {
- html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
- }
+ function appendInteger(object, html) {
+ html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+ }
- function appendFloat(object, html) {
- html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
- }
+ function appendFloat(object, html) {
+ html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+ }
- function appendFunction(object, html) {
- var reName = /function ?(.*?)\(/;
- var m = reName.exec(objectToString(object));
- var name = m ? m[1] : "function";
- html.push('<span class="objectBox-function">', escapeHTML(name), '()</span>');
- }
+ function appendFunction(object, html) {
+ var reName = /function ?(.*?)\(/;
+ var m = reName.exec(objectToString(object));
+ var name = m ? m[1] : "function";
+ html.push('<span class="objectBox-function">', escapeHTML(name), '()</span>');
+ }
- function appendArray(object, html) {
- html.push('<span class="arrayLeftBracket">[</span>');
- for (var i = 0; i < object.length; ++i) {
- if (i > 0) {
- html.push('<span class="arrayComma">,</span>');
+ function appendArray(object, html) {
+ html.push('<span class="arrayLeftBracket">[</span>');
+ for (var i = 0; i < object.length; ++i) {
+ if (i > 0) {
+ html.push('<span class="arrayComma">,</span>');
+ }
+ appendObject(object[i], html);
}
- appendObject(object[i], html);
+ html.push('<span class="arrayRightBracket">]</span>');
}
- html.push('<span class="arrayRightBracket">]</span>');
- }
-
- function appendObject(object, html) {
- try {
- if (object == undefined) {
- appendNull("undefined", html);
- } else if (object == null) {
- appendNull("null", html);
- } else if (typeof object == "string") {
- appendString(object, html);
- } else if (typeof object == "number") {
- appendInteger(object, html);
- } else if (object.nodeType == 1) {
- appendSelector(object, html);
- } else if (object == window || object == document) {
- appendObjectFormatted(object, html);
- } else if (typeof(object.length) == "number") {
- appendArray(object, html);
- } else if (typeof object == "object") {
- appendObjectFormatted(object, html);
- } else if (typeof object == "function") {
- appendFunction(object, html);
- } else {
- appendText(object, html);
+
+ function appendObject(object, html) {
+ try {
+ if (object == undefined) {
+ appendNull("undefined", html);
+ } else if (object == null) {
+ appendNull("null", html);
+ } else if (typeof object == "string") {
+ appendString(object, html);
+ } else if (typeof object == "number") {
+ appendInteger(object, html);
+ } else if (object.nodeType == 1) {
+ appendSelector(object, html);
+ } else if (object == window || object == document) {
+ appendObjectFormatted(object, html);
+ } else if (typeof(object.length) == "number") {
+ appendArray(object, html);
+ } else if (typeof object == "object") {
+ appendObjectFormatted(object, html);
+ } else if (typeof object == "function") {
+ appendFunction(object, html);
+ } else {
+ appendText(object, html);
+ }
+ } catch (exc) {
}
- } catch (exc) { }
- }
-
- function appendObjectFormatted(object, html) {
- var text = objectToString(object);
- reObject = /\[object (.*?)\]/;
- m = reObject.exec(text);
+ }
- html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>');
- }
-
- function appendSelector(object, html) {
- html.push('<span class="objectBox-selector">');
+ function appendObjectFormatted(object, html) {
+ var text = objectToString(object);
+ var reObject = /\[object (.*?)\]/;
+ var m = reObject.exec(text);
+
+ html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>');
+ }
- html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
- if (object.id)
- html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
- if (object.className)
- html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
+ function appendSelector(object, html) {
+ html.push('<span class="objectBox-selector">');
- html.push('</span>');
- }
+ html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
+ if (object.id)
+ html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
+ if (object.className)
+ html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
- function appendNode(node, html) {
- if (node.nodeType == 1) {
- html.push(
- '<div class="objectBox-element">',
- '&lt;<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
-
- for (var i = 0; i < node.attributes.length; ++i) {
- var attr = node.attributes[i];
- if (!attr.specified)
- continue;
-
- html.push('&nbsp;<span class="nodeName">', attr.nodeName.toLowerCase(),
- '</span>=&quot;<span class="nodeValue">', escapeHTML(attr.nodeValue),
- '</span>&quot;');
- }
+ html.push('</span>');
+ }
- if (node.firstChild) {
- html.push('&gt;</div><div class="nodeChildren">');
+ function appendNode(node, html) {
+ if (node.nodeType == 1) {
+ html.push(
+ '<div class="objectBox-element">',
+ '&lt;<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
- for (var child = node.firstChild; child; child = child.nextSibling)
- appendNode(child, html);
-
- html.push('</div><div class="objectBox-element">&lt;/<span class="nodeTag">',
- node.nodeName.toLowerCase(), '&gt;</span></div>');
- }
- else {
- html.push('/&gt;</div>');
+ for (var i = 0; i < node.attributes.length; ++i) {
+ var attr = node.attributes[i];
+ if (!attr.specified)
+ continue;
+
+ html.push('&nbsp;<span class="nodeName">', attr.nodeName.toLowerCase(),
+ '</span>=&quot;<span class="nodeValue">', escapeHTML(attr.nodeValue),
+ '</span>&quot;');
+ }
+
+ if (node.firstChild) {
+ html.push('&gt;</div><div class="nodeChildren">');
+
+ for (var child = node.firstChild; child; child = child.nextSibling)
+ appendNode(child, html);
+
+ html.push('</div><div class="objectBox-element">&lt;/<span class="nodeTag">',
+ node.nodeName.toLowerCase(), '&gt;</span></div>');
+ }
+ else {
+ html.push('/&gt;</div>');
+ }
+ } else if (node.nodeType == 3) {
+ html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
+ '</div>');
}
- } else if (node.nodeType == 3) {
- html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
- '</div>');
}
- }
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- function logRow(message, className, handler) {
- sendMessage(className + "||" + message.join(""));
- }
-
- function logFormatted(objects, className) {
- var html = [];
+ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+ function logRow(message, className) {
+ sendMessage(className + "||" + message.join(""));
+ }
- var format = objects[0];
- var objIndex = 0;
- if (typeof format != "string") {
- format = "";
- objIndex = -1;
+ function pushGroup(message, className) {
+ logFormatted('pushGroup||' + message, className);
}
-
- var parts = parseFormat(format);
- for (var i = 0; i < parts.length; ++i) {
- var part = parts[i];
- if (part && typeof(part) == "object") {
- var object = objects[++objIndex];
- part.appender(object, html);
+
+ function popGroup() {
+ logFormatted('popGroup', '');
+ }
+
+ function logFormatted(objects, className) {
+ var html = [];
+
+ var format = objects[0];
+ var objIndex = 0;
+ var object;
+
+ if (typeof format != "string") {
+ format = "";
+ objIndex = -1;
}
- else {
- appendText(part, html);
+
+ var parts = parseFormat(format);
+ for (var i = 0; i < parts.length; ++i) {
+ var part = parts[i];
+ if (part && typeof(part) == "object") {
+ object = objects[++objIndex];
+ part.appender(object, html);
+ }
+ else {
+ appendText(part, html);
+ }
}
- }
- for (var i = objIndex+1; i < objects.length; ++i) {
- appendText(" ", html);
-
- var object = objects[i];
- if (typeof(object) == "string") {
- appendText(object, html);
- } else {
- appendObject(object, html);
+ for (i = objIndex + 1; i < objects.length; ++i) {
+ appendText(" ", html);
+
+ object = objects[i];
+ if (typeof(object) == "string") {
+ appendText(object, html);
+ } else {
+ appendObject(object, html);
+ }
}
+
+ if (!className && html.length == 1 && typeof objects[0] == "string") {
+ className = "text";
+ }
+
+ logRow(html, className);
}
-
- if (!className && html.length == 1 && typeof objects[0] == "string") {
- className = "text";
- }
-
- logRow(html, className);
- }
- function parseFormat(format) {
- var parts = [];
+ function parseFormat(format) {
+ var parts = [];
- var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
- var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
+ var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
+ var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
- for (var m = reg.exec(format); m; m = reg.exec(format)) {
- var type = m[8] ? m[8] : m[5];
- var appender = type in appenderMap ? appenderMap[type] : appendObject;
- var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
+ for (var m = reg.exec(format); m; m = reg.exec(format)) {
+ var type = m[8] ? m[8] : m[5];
+ var appender = type in appenderMap ? appenderMap[type] : appendObject;
+ var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
- parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
- parts.push({appender: appender, precision: precision});
+ parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index + 1));
+ parts.push({appender: appender, precision: precision});
- format = format.substr(m.index+m[0].length);
- }
+ format = format.substr(m.index + m[0].length);
+ }
- parts.push(format);
+ parts.push(format);
- return parts;
- }
+ return parts;
+ }
- function escapeHTML(value) {
- function replaceChars(ch) {
- switch (ch) {
- case "<":
- return "&lt;";
- case ">":
- return "&gt;";
- case "&":
- return "&amp;";
- case "'":
- return "&#39;";
- case '"':
- return "&quot;";
+ function escapeHTML(value) {
+ function replaceChars(ch) {
+ switch (ch) {
+ case "<":
+ return "&lt;";
+ case ">":
+ return "&gt;";
+ case "&":
+ return "&amp;";
+ case "'":
+ return "&#39;";
+ case '"':
+ return "&quot;";
+ }
+ return "?";
}
- return "?";
- };
- return String(value).replace(/[<>&"']/g, replaceChars);
- }
- function objectToString(object) {
- try {
- return object+"";
- } catch (exc) {
- return null;
+ return String(value).replace(/[<>&"']/g, replaceChars);
}
- }
- setTimeout(init, 0);
-})();
-}
+ function objectToString(object) {
+ try {
+ return object + "";
+ } catch (exc) {
+ return null;
+ }
+ }
+
+ init();
+ window.addEventListener("DOMContentLoaded", listen, false);
+ })();
+}
View
147 ibug.py
@@ -1,147 +0,0 @@
-import socket
-import mimetypes
-import logging
-import os
-
-import tornado.httpserver
-import tornado.ioloop
-import tornado.web
-
-# Doesn't seem to work w/ localhost, so fake it with /etc/hosts
-HOST = "m.com"
-
-# Port _MUST_ be 80 in this implementation.
-PORT = 80
-
-
-# Utils ************************************************************************
-
-def escape_js(s):
- return s.replace("'", "\\'").replace("\n", "\\n").replace("\r", "")
-
-def get_host_info():
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s.connect(("getfirebug.com", 80))
- host = s.getsockname()[0]
- s.close()
- # return {"host": host, "port": port}
- return {"host": HOST, "port": PORT}
-
-
-# Utils ************************************************************************
-
-class MessageMixin(object):
- """
- Based on:
- http://github.com/facebook/tornado/blob/master/demos/chat/chatdemo.py
-
- """
- phone_waiters = []
- console_waiters = []
-
- def wait_for_phone_message(self, callback):
- MessageMixin.phone_waiters.append(callback)
-
- def new_phone_message(self, message):
- for callback in MessageMixin.phone_waiters:
- callback(message)
- MessageMixin.phone_waiters = []
-
- def wait_for_console_message(self, callback):
- MessageMixin.console_waiters.append(callback)
-
- def new_console_message(self, message):
- for callback in MessageMixin.console_waiters:
- callback(message)
- MessageMixin.console_waiters = []
-
-
-# Handlers *********************************************************************
-
-class CommandHandler(tornado.web.RequestHandler, MessageMixin):
- @tornado.web.asynchronous
- def get(self):
- message = self.request.arguments.get("message")[0]
- self.new_phone_message(message)
- print 'waiting for console'
- self.wait_for_console_message(self.async_callback(self.on_new_message))
-
- def on_new_message(self, message):
- if self.request.connection.stream.closed():
- return
- self.set_header("Content-Type", "application/x-javascript")
- self.finish(message)
-
-class BrowserHandler(tornado.web.RequestHandler, MessageMixin):
- @tornado.web.asynchronous
- def get(self):
- self.write(file("browser.html").read())
- self.wait_for_console_message(self.async_callback(self.on_new_message))
-
- def on_new_message(self, message):
- if self.request.connection.stream.closed():
- return
- self.finish("<script>command('%s')</script>" % escape_js(message))
-
-class ResponseHandler(tornado.web.RequestHandler, MessageMixin):
- def get(self):
- message = self.request.arguments.get("message")[0]
- self.new_console_message(message)
- self.write('')
-
-
-class PhoneHandler(tornado.web.RequestHandler, MessageMixin):
- @tornado.web.asynchronous
- def get(self):
- self.write(file("phone.html").read())
- self.wait_for_phone_message(self.async_callback(self.on_new_message))
-
- def on_new_message(self, message):
- if self.request.connection.stream.closed():
- return
- self.finish("<script>command('%s')</script>" % escape_js(message))
-
-
-class ScriptHandler(tornado.web.RequestHandler):
- def get(self):
- path = self.request.path.split("/")[-1]
- mimetype = mimetypes.guess_type(path)[0]
- self.set_header("Content-Type", mimetype)
- # @@@ Always run off 80.
- # self.write("var ibugHost = '%(host)s:%(port)s';" % get_host_info())
- self.write("var ibugHost = '%(host)s';" % get_host_info())
- self.write(file(path).read())
-
-
-class FileHandler(tornado.web.RequestHandler):
- def get(self):
- path = self.request.path.split("/")[-1]
- mimetype = mimetypes.guess_type(path)[0]
- self.set_header("Content-Type", mimetype)
-
- try:
- self.write(file(path).read())
- except:
- self.write('')
-
-
-# Application ******************************************************************
-
-settings = {
- "static_path": os.path.join(os.path.dirname(__file__), "static"),
-}
-
-application = tornado.web.Application([
- (r"/command", CommandHandler),
- (r"/response", ResponseHandler),
- (r"/browser", BrowserHandler),
- (r"/phone", PhoneHandler),
- (r"/\w+\.js", ScriptHandler),
- (r".*", FileHandler)
-])
-
-
-if __name__ == "__main__":
- http_server = tornado.httpserver.HTTPServer(application)
- http_server.listen(PORT)
- tornado.ioloop.IOLoop.instance().start()
View
27 phone.html
@@ -1,27 +0,0 @@
-<html>
-<head></head>
-<body>
-<script type="text/javascript">
-
-var host = window.location.host;
-
-function command(text)
-{
- parent.console.command(text);
-}
-
-function respond(text)
-{
- // Send the message using an img instead of XMLHttpRequest to avoid cross-domain security
- var img = document.createElement("img");
- img.style.visibility = "hidden";
- document.body.appendChild(img);
- img.onerror = function() { img.parentNode.removeChild(img); }
-
- var message = escape(text);
- img.src = "http://" + host + "/response?message=" + message;
-}
-
-parent.console.handshake(respond);
-
-</script>
View
40 queue.js
@@ -0,0 +1,40 @@
+var queue = exports;
+
+queue.queue = function() {
+
+ var queue = [];
+
+ var queueSpace = 0;
+
+ this.Count = function() {
+ return queue.length - queueSpace;
+ }
+
+ this.IsEmpty = function() {
+
+ // return true if the queue is empty, and false otherwise
+ return (queue.length == 0);
+
+ }
+
+ this.Enqueue = function(element) {
+ queue.push(element);
+ }
+
+ this.Dequeue = function() {
+
+ var element = undefined;
+
+ if (queue.length) {
+
+ element = queue[queueSpace];
+
+ if (++queueSpace * 2 >= queue.length) {
+ queue = queue.slice(queueSpace);
+ queueSpace = 0;
+ }
+ }
+
+ return element;
+ }
+}
View
191 server.js
@@ -1,5 +1,6 @@
// Node documentation: http://nodejs.org/api.html
// Based on node_chat: http://github.com/ry/node_chat
+var queue = require("./queue");
var fu = require("./fu");
var sys = require("sys");
var url = require("url");
@@ -15,7 +16,7 @@ if (process.ARGV.length > 2) {
var _url = url.parse("http://" + process.ARGV[2]);
HOST = _url.hostname;
- PORT = _url.port;
+ PORT = _url.port;
}
var escapeJS = function (s) {
@@ -23,54 +24,89 @@ var escapeJS = function (s) {
}
var channel = new function () {
- var client = { queue: {}
- , callback: null };
- var console = { queue: {}
- , callback: null };
-
- this.getQueue = function (queueName) {
- return (queueName == "client" && client) || console;
- }
-
- // Message are broken into bits, so queue them until we recieve all the bits.
- this.queue = function (queueName, encodedBit, messageNumber, bitLength, bitNumber) {
- var queue = this.getQueue(queueName);
-
- // [bit1, bit2, bit3, ..., bitx, number_of_bits_recieved]
- if (!queue[messageNumber]) {
- queue[messageNumber] = [];
- queue[messageNumber][bitLength] = 1;
- } else {
- queue[messageNumber][bitLength]++;
- }
-
- queue[messageNumber][bitNumber] = encodedBit
-
- // If all bits in a message are here, send it.
- if (queue[messageNumber][bitLength] == bitLength && queue.callback) {
- var message;
- var callback = queue.callback;
- queue.callback = null;