diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/WebKitTools/Drosera/debugger.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKitTools/Drosera/debugger.js Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,1433 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2007 Vladimir Olexa (vladimir.olexa@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var files = new Array();
+var filesLookup = new Object();
+var scripts = new Array();
+var currentFile = -1;
+var currentRow = null;
+var currentStack = null;
+var currentCallFrame = null;
+var lastStatement = null;
+var frameLineNumberStack = new Array();
+var previousFiles = new Array();
+var nextFiles = new Array();
+var isResizingColumn = false;
+var draggingBreakpoint = null;
+var steppingOut = false;
+var steppingOver = false;
+var steppingStack = 0;
+var pauseOnNextStatement = false;
+var pausedWhileLeavingFrame = false;
+var consoleWindow = null;
+var breakpointEditorHTML = DebuggerDocument.breakpointEditorHTML();
+var pendingAction = null;
+var isPaused = false;
+
+ScriptCallFrame = function (functionName, index, row)
+{
+ this.functionName = functionName;
+ this.index = index;
+ this.row = row;
+ this.localVariableNames = null;
+}
+
+ScriptCallFrame.prototype.valueForScopeVariable = function (name)
+{
+ return DebuggerDocument.valueForScopeVariableNamed(name, this.index);
+}
+
+ScriptCallFrame.prototype.loadVariables = function ()
+{
+ if (!this.localVariableNames)
+ this.localVariableNames = DebuggerDocument.localScopeVariableNamesForCallFrame(this.index);
+
+ var variablesTable = document.getElementById("variablesTable");
+ variablesTable.innerHTML = "";
+
+ if (!this.localVariableNames)
+ return;
+
+ for(var i = 0; i < this.localVariableNames.length; i++) {
+ var tr = document.createElement("tr");
+ var td = document.createElement("td");
+ td.innerText = this.localVariableNames[i];
+ td.className = "variable";
+ tr.appendChild(td);
+
+ td = document.createElement("td");
+ td.innerText = this.valueForScopeVariable(this.localVariableNames[i]);
+ tr.appendChild(td);
+ tr.addEventListener("click", selectVariable, true);
+
+ variablesTable.appendChild(tr);
+ }
+}
+
+function sleep(numberMillis)
+{
+ var now = new Date();
+ var exitTime = now.getTime() + numberMillis;
+ while (true) {
+ now = new Date();
+ if (now.getTime() > exitTime)
+ return;
+ }
+}
+
+function headerMouseDown(element)
+{
+ if (!isResizingColumn)
+ element.style.background = "url(glossyHeaderPressed.png) repeat-x";
+}
+
+function headerMouseUp(element)
+{
+ element.style.background = "url(glossyHeader.png) repeat-x";
+}
+
+function headerMouseOut(element)
+{
+ element.style.background = "url(glossyHeader.png) repeat-x";
+}
+
+function filesDividerDragStart(event)
+{
+ dividerDragStart(document.getElementById("filesDivider"), filesDividerDrag, filesDividerDragEnd, event, "col-resize");
+}
+
+function filesDividerDragEnd(event)
+{
+ dividerDragEnd(document.getElementById("filesDivider"), filesDividerDrag, filesDividerDragEnd, event);
+}
+
+function filesDividerDrag(event)
+{
+ var element = document.getElementById("filesDivider");
+ if (document.getElementById("filesDivider").dragging == true) {
+ var masterMain = document.getElementById("masterMain");
+ var main = document.getElementById("main");
+ var fileBrowser = document.getElementById("fileBrowser");
+ var x = event.clientX + window.scrollX;
+ var delta = element.dragLastX - x;
+ var newWidth = constrainedWidthFromElement(fileBrowser.clientWidth - delta, masterMain, 0.1, 0.9);
+ if ((fileBrowser.clientWidth - delta) == newWidth) // the width wasn't constrained
+ element.dragLastX = x;
+ fileBrowser.style.width = newWidth + "px";
+ main.style.left = newWidth + "px";
+ event.preventDefault();
+ }
+}
+
+function dividerDragStart(element, dividerDrag, dividerDragEnd, event, cursor)
+{
+ element.dragging = true;
+ element.dragLastY = event.clientY + window.scrollY;
+ element.dragLastX = event.clientX + window.scrollX;
+ document.addEventListener("mousemove", dividerDrag, true);
+ document.addEventListener("mouseup", dividerDragEnd, true);
+ document.body.style.cursor = cursor;
+ event.preventDefault();
+}
+
+function dividerDragEnd(element, dividerDrag, dividerDragEnd, event)
+{
+ element.dragging = false;
+ document.removeEventListener("mousemove", dividerDrag, true);
+ document.removeEventListener("mouseup", dividerDragEnd, true);
+ document.body.style.removeProperty("cursor");
+}
+
+function dividerDrag(event)
+{
+ var element = document.getElementById("divider");
+ if (document.getElementById("divider").dragging == true) {
+ var main = document.getElementById("main");
+ var top = document.getElementById("info");
+ var bottom = document.getElementById("body");
+ var y = event.clientY + window.scrollY;
+ var delta = element.dragLastY - y;
+ var newHeight = constrainedHeightFromElement(top.clientHeight - delta, main);
+ if ((top.clientHeight - delta) == newHeight) // the height wasn't constrained
+ element.dragLastY = y;
+ top.style.height = newHeight + "px";
+ bottom.style.top = newHeight + "px";
+ event.preventDefault();
+ }
+}
+
+function sourceDividerDragStart(event)
+{
+ dividerDragStart(document.getElementById("divider"), dividerDrag, sourceDividerDragEnd, event, "row-resize");
+}
+
+function sourceDividerDragEnd(event)
+{
+ dividerDragEnd(document.getElementById("divider"), dividerDrag, sourceDividerDragEnd, event);
+}
+
+function infoDividerDragStart(event)
+{
+ dividerDragStart(document.getElementById("infoDivider"), infoDividerDrag, infoDividerDragEnd, event, "col-resize");
+}
+
+function infoDividerDragEnd(event)
+{
+ dividerDragEnd(document.getElementById("infoDivider"), infoDividerDrag, infoDividerDragEnd, event);
+}
+
+function infoDividerDrag(event)
+{
+ var element = document.getElementById("infoDivider");
+ if (document.getElementById("infoDivider").dragging == true) {
+ var main = document.getElementById("main");
+ var leftPane = document.getElementById("leftPane");
+ var rightPane = document.getElementById("rightPane");
+ var x = event.clientX + window.scrollX;
+ var delta = element.dragLastX - x;
+ var newWidth = constrainedWidthFromElement(leftPane.clientWidth - delta, main);
+ if ((leftPane.clientWidth - delta) == newWidth) // the width wasn't constrained
+ element.dragLastX = x;
+ leftPane.style.width = newWidth + "px";
+ rightPane.style.left = newWidth + "px";
+ event.preventDefault();
+ }
+}
+
+function columnResizerDragStart(event)
+{
+ isResizingColumn = true;
+ dividerDragStart(document.getElementById("variableColumnResizer"), columnResizerDrag, columnResizerDragEnd, event, "col-resize");
+}
+
+function columnResizerDragEnd(event)
+{
+ isResizingColumn = false;
+ dividerDragEnd(document.getElementById("variableColumnResizer"), columnResizerDrag, columnResizerDragEnd, event);
+}
+
+function columnResizerDrag(event)
+{
+ var element = document.getElementById("variableColumnResizer");
+ if (element.dragging == true) {
+ var main = document.getElementById("rightPane");
+ var variableColumn = document.getElementById("variable");
+ var rules = document.defaultView.getMatchedCSSRules(variableColumn, "");
+ for (var i = 0; i < rules.length; i++) {
+ if (rules[i].selectorText == ".variable") {
+ var columnRule = rules[i];
+ break;
+ }
+ }
+
+ var x = event.clientX + window.scrollX;
+ var delta = element.dragLastX - x;
+ var newWidth = constrainedWidthFromElement(variableColumn.clientWidth - delta, main);
+ if ((variableColumn.clientWidth - delta) == newWidth) // the width wasn't constrained
+ element.dragLastX = x;
+ columnRule.style.width = newWidth + "px";
+ element.style.left = newWidth + "px";
+ event.preventDefault();
+ }
+}
+
+function constrainedWidthFromElement(width, element, constrainLeft, constrainRight)
+{
+ if (constrainLeft === undefined) constrainLeft = 0.25;
+ if (constrainRight === undefined) constrainRight = 0.75;
+
+ if (width < element.clientWidth * constrainLeft)
+ width = element.clientWidth * constrainLeft;
+ else if (width > element.clientWidth * constrainRight)
+ width = element.clientWidth * constrainRight;
+ return width;
+}
+
+function constrainedHeightFromElement(height, element)
+{
+ if (height < element.clientHeight * 0.25)
+ height = element.clientHeight * 0.25;
+ else if (height > element.clientHeight * 0.75)
+ height = element.clientHeight * 0.75;
+ return height;
+}
+
+function loaded()
+{
+ document.getElementById("divider").addEventListener("mousedown", sourceDividerDragStart, false);
+ document.getElementById("infoDivider").addEventListener("mousedown", infoDividerDragStart, false);
+ document.getElementById("filesDivider").addEventListener("mousedown", filesDividerDragStart, false);
+ document.getElementById("variableColumnResizer").addEventListener("mousedown", columnResizerDragStart, false);
+}
+
+function pause()
+{
+ DebuggerDocument.pause();
+ isPaused = true;
+}
+
+function resume()
+{
+ if (currentRow) {
+ currentRow.removeStyleClass("current");
+ currentRow = null;
+ }
+
+ var stackframeTable = document.getElementById("stackframeTable");
+ stackframeTable.innerHTML = ""; // clear the content
+ var variablesTable = document.getElementById("variablesTable");
+ variablesTable.innerHTML = ""; // clear the content
+ currentStack = null;
+ currentCallFrame = null;
+
+ pauseOnNextStatement = false;
+ pausedWhileLeavingFrame = false;
+ steppingOut = false;
+ steppingOver = false;
+ steppingStack = 0;
+
+ DebuggerDocument.resume();
+ isPaused = false;
+}
+
+function stepInto()
+{
+ pauseOnNextStatement = false;
+ steppingOut = false;
+ steppingOver = false;
+ steppingStack = 0;
+ DebuggerDocument.stepInto();
+}
+
+function stepOver()
+{
+ pauseOnNextStatement = false;
+ steppingOver = true;
+ steppingStack = 0;
+ DebuggerDocument.resume();
+}
+
+function stepOut()
+{
+ pauseOnNextStatement = pausedWhileLeavingFrame;
+ steppingOver = false;
+ steppingStack = 0;
+ steppingOut = true;
+ DebuggerDocument.resume();
+}
+
+Element.prototype.removeStyleClass = function(className)
+{
+ if (this.hasStyleClass(className))
+ this.className = this.className.replace(className, "");
+}
+
+Element.prototype.addStyleClass = function(className)
+{
+ if (!this.hasStyleClass(className))
+ this.className += (this.className.length ? " " + className : className);
+}
+
+Element.prototype.hasStyleClass = function(className)
+{
+ return this.className.indexOf(className) != -1;
+}
+
+Element.prototype.firstParentWithClass = function(className)
+{
+ var node = this.parentNode;
+ while(!node.hasStyleClass(className)) {
+ if (node == document)
+ return null;
+ node = node.parentNode;
+ }
+ return node;
+}
+
+Element.prototype.query = function(query)
+{
+ return document.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
+}
+
+Element.prototype.removeChildren = function()
+{
+ while (this.firstChild)
+ this.removeChild(this.firstChild);
+}
+
+function breakpointAction(event)
+{
+ var file = files[currentFile];
+ var lineNum = event.target.title;
+
+ if (!file.breakpoints[lineNum])
+ file.breakpoints[lineNum] = new BreakPoint(event.target.parentNode, file, lineNum);
+ else
+ toggleBreakpointOnLine(lineNum);
+}
+
+BreakPoint = function(row, file, line)
+{
+ this.row = row;
+ this.file = file;
+ this.line = line;
+ row.addStyleClass("breakpoint");
+ row.removeStyleClass("disabled");
+ this.value = "break";
+ this.enabled = true;
+ this.editor = null;
+ this.type = 0;
+ this.hitcount = 0;
+}
+
+function toggleBreakpointEditorOnLine(lineNum)
+{
+ if (pendingAction) {
+ clearTimeout(pendingAction);
+ pendingAction = null;
+ }
+ var file = files[currentFile];
+ bp = file.breakpoints[lineNum];
+ if (bp) {
+ var editor = bp.editor;
+ if (!editor) {
+ var sourcesDocument = document.getElementById("sources").contentDocument;
+ editor = sourcesDocument.createElement("div");
+ editor.className = "editor";
+ editor.id = lineNum;
+ editor.innerHTML = breakpointEditorHTML;
+
+ bp.row.childNodes[1].appendChild(editor);
+
+ bp.editor = editor;
+ file.breakpoints[lineNum] = bp;
+
+ editor.query('.//input[@class="enable"]').checked = bp.enabled;
+
+ editor.query('.//select[@class="editorDropdown"]').selectedIndex = bp.type;
+ updateBreakpointTypeOnLine(lineNum);
+
+ editor.query('.//span[@class="hitCounter"]').innerText = bp.hitcount;
+
+ setConditionFieldText(bp);
+ } else {
+ saveBreakpointOnLine(lineNum);
+ bp.row.childNodes[1].removeChild(editor);
+ bp.editor = null;
+ }
+ }
+}
+
+function updateBreakpointTypeOnLine(line)
+{
+ var breakpoint = files[currentFile].breakpoints[line];
+ var editor = breakpoint.editor;
+ var label = editor.query('.//label[@class="conditionLabel"]');
+ var dropdown = editor.query('.//select[@class="editorDropdown"]');
+ breakpoint.type = dropdown.selectedIndex;
+ switch(breakpoint.type) {
+ case 0:
+ label.innerText = "Condition:";
+ break;
+ case 1:
+ label.innerText = "Expression:";
+ break;
+ }
+}
+
+function setConditionFieldText(breakpoint)
+{
+ var conditionField = breakpoint.editor.query('.//div[@class="condition"]');
+
+ var functionBody = breakpoint.value;
+ if (!functionBody || functionBody == "break")
+ functionBody = "";
+ else {
+ var startIndex = functionBody.indexOf("return((") + 8;
+ var endIndex = null;
+ if (startIndex != 7) //-1 + 8, yes, that's lame
+ endIndex = functionBody.lastIndexOf("))");
+ else {
+ startIndex = functionBody.indexOf("{") + 1;
+ endIndex = functionBody.lastIndexOf("}");
+ }
+ functionBody = functionBody.substring(startIndex, endIndex);
+ }
+ conditionField.innerText = functionBody;
+ conditionField.addEventListener("keyup", new Function("saveBreakpointOnLine(" + breakpoint.line + ");"), false);
+ conditionField.focus();
+}
+
+function saveBreakpointOnLine(lineNum)
+{
+ var file = files[currentFile];
+ var breakpoint = file.breakpoints[lineNum];
+ row = file.element.firstChild.childNodes.item(lineNum - 1);
+ var editor = breakpoint.editor;
+ var body = editor.query('.//div[@class="condition"]').innerText;
+ var actionIndex = editor.query('.//select[@class="editorDropdown"]').selectedIndex;
+ if (body.length == 0)
+ breakpoint.value = "break";
+ else if (body.indexOf("return") != -1)
+ breakpoint.value = "__drosera_breakpoint_conditional_func = function() {" + body + "}; __drosera_breakpoint_conditional_func();";
+ else
+ breakpoint.value = "__drosera_breakpoint_conditional_func = function() { return((" + body + ")); }; __drosera_breakpoint_conditional_func();";
+}
+
+function toggleBreakpointOnLine(lineNum)
+{
+ var breakpoint = files[currentFile].breakpoints[lineNum];
+ pendingAction = null;
+ if (breakpoint.enabled)
+ breakpoint.row.addStyleClass("disabled");
+ else
+ breakpoint.row.removeStyleClass("disabled");
+
+ var hack = breakpoint.row.offsetTop; // force a relayout if needed.
+
+ breakpoint.enabled = !breakpoint.enabled;
+ var editor = breakpoint.editor;
+ if (editor) {
+ editor.query('.//input[@class="enable"]').checked = breakpoint.enabled;
+ setConditionFieldText(breakpoint, lineNum);
+ }
+}
+
+function moveBreakPoint(event)
+{
+ if (event.target.parentNode.hasStyleClass("breakpoint")) {
+ draggingBreakpoint = event.target;
+ draggingBreakpoint.started = false;
+ draggingBreakpoint.dragLastY = event.clientY + window.scrollY;
+ draggingBreakpoint.dragLastX = event.clientX + window.scrollX;
+ var sourcesDocument = document.getElementById("sources").contentDocument;
+ sourcesDocument.addEventListener("mousemove", breakpointDrag, true);
+ sourcesDocument.addEventListener("mouseup", breakpointDragEnd, true);
+ sourcesDocument.body.style.cursor = "default";
+ }
+}
+
+function breakpointDrag(event)
+{
+ var sourcesDocument = document.getElementById("sources").contentDocument;
+ if (!draggingBreakpoint) {
+ sourcesDocument.removeEventListener("mousemove", breakpointDrag, true);
+ sourcesDocument.removeEventListener("mouseup", breakpointDragEnd, true);
+ sourcesDocument.body.style.removeProperty("cursor");
+ return;
+ }
+
+ var x = event.clientX + window.scrollX;
+ var y = event.clientY + window.scrollY;
+ var deltaX = draggingBreakpoint.dragLastX - x;
+ var deltaY = draggingBreakpoint.dragLastY - y;
+ if (draggingBreakpoint.started || deltaX > 4 || deltaY > 4 || deltaX < -4 || deltaY < -4) {
+
+ if (!draggingBreakpoint.started) {
+ var lineNum = draggingBreakpoint.title;
+ var file = files[currentFile];
+ var breakpoint = file.breakpoints[lineNum];
+ draggingBreakpoint.breakpoint = breakpoint;
+ breakpoint.row.removeStyleClass("breakpoint");
+ breakpoint.row.removeStyleClass("disabled");
+
+ var editor = breakpoint.editor;
+ if (editor)
+ toggleBreakpointEditorOnLine(lineNum);
+
+ draggingBreakpoint.started = true;
+
+ file.breakpoints[lineNum] = null;
+
+ var dragImage = sourcesDocument.createElement("img");
+ if (draggingBreakpoint.breakpoint.enabled)
+ dragImage.src = "breakPoint.tif";
+ else
+ dragImage.src = "breakPointDisabled.tif";
+
+ dragImage.id = "breakpointDrag";
+ dragImage.style.top = y - 8 + "px";
+ dragImage.style.left = x - 12 + "px";
+ sourcesDocument.body.appendChild(dragImage);
+ } else {
+ var dragImage = sourcesDocument.getElementById("breakpointDrag");
+ if (!dragImage) {
+ sourcesDocument.removeEventListener("mousemove", breakpointDrag, true);
+ sourcesDocument.removeEventListener("mouseup", breakpointDragEnd, true);
+ sourcesDocument.body.style.removeProperty("cursor");
+ return;
+ }
+
+ dragImage.style.top = y - 8 + "px";
+ dragImage.style.left = x - 12 + "px";
+ if (x > 40)
+ dragImage.style.visibility = "hidden";
+ else
+ dragImage.style.removeProperty("visibility");
+ }
+
+ draggingBreakpoint.dragLastX = x;
+ draggingBreakpoint.dragLastY = y;
+ }
+}
+
+function breakpointDragEnd(event)
+{
+ var sourcesDocument = document.getElementById("sources").contentDocument;
+ sourcesDocument.removeEventListener("mousemove", breakpointDrag, true);
+ sourcesDocument.removeEventListener("mouseup", breakpointDragEnd, true);
+ sourcesDocument.body.style.removeProperty("cursor");
+
+ var dragImage = sourcesDocument.getElementById("breakpointDrag");
+ if (!dragImage)
+ return;
+
+ dragImage.parentNode.removeChild(dragImage);
+
+ var x = event.clientX + window.scrollX;
+ if (x > 40 || !draggingBreakpoint)
+ return;
+
+ var y = event.clientY + window.scrollY;
+ var rowHeight = draggingBreakpoint.parentNode.offsetHeight;
+ var row = Math.ceil(y / rowHeight);
+ if (row <= 0)
+ row = 1;
+
+ var file = files[currentFile];
+ var table = file.element.firstChild;
+ if (row > table.childNodes.length)
+ return;
+
+ var tr = table.childNodes.item(row - 1);
+ if (!tr)
+ return;
+
+ var breakpoint = draggingBreakpoint.breakpoint;
+ breakpoint.row = tr;
+
+ // leave the editor there if it exists... we'll want to update it to the new values
+ breakpoint.editor = file.breakpoints[row].editor;
+
+ file.breakpoints[row] = breakpoint;
+
+ if (breakpoint.editor) {
+ breakpoint.editor.id = row;
+ updateBreakpointTypeOnLine(row);
+ setConditionFieldText(breakpoint);
+ }
+
+ if (!breakpoint.enabled)
+ tr.addStyleClass("disabled");
+
+ tr.addStyleClass("breakpoint");
+
+ draggingBreakpoint = null;
+}
+
+function totalOffsetTop(element, stop)
+{
+ var currentTop = 0;
+ while (element.offsetParent) {
+ currentTop += element.offsetTop
+ element = element.offsetParent;
+ if (element == stop)
+ break;
+ }
+ return currentTop;
+}
+
+function switchFile(fileIndex)
+{
+ var filesSelect = document.getElementById("files");
+
+ if (fileIndex === undefined)
+ fileIndex = filesSelect.selectedIndex;
+
+ fileClicked(filesSelect.options[fileIndex].value, false);
+ loadFile(filesSelect.options[fileIndex].value, true);
+}
+
+function syntaxHighlight(code, file)
+{
+ var keywords = { 'abstract': 1, 'boolean': 1, 'break': 1, 'byte': 1, 'case': 1, 'catch': 1, 'char': 1, 'class': 1, 'const': 1, 'continue': 1, 'debugger': 1, 'default': 1, 'delete': 1, 'do': 1, 'double': 1, 'else': 1, 'enum': 1, 'export': 1, 'extends': 1, 'false': 1, 'final': 1, 'finally': 1, 'float': 1, 'for': 1, 'function': 1, 'goto': 1, 'if': 1, 'implements': 1, 'import': 1, 'in': 1, 'instanceof': 1, 'int': 1, 'interface': 1, 'long': 1, 'native': 1, 'new': 1, 'null': 1, 'package': 1, 'private': 1, 'protected': 1, 'public': 1, 'return': 1, 'short': 1, 'static': 1, 'super': 1, 'switch': 1, 'synchronized': 1, 'this': 1, 'throw': 1, 'throws': 1, 'transient': 1, 'true': 1, 'try': 1, 'typeof': 1, 'var': 1, 'void': 1, 'volatile': 1, 'while': 1, 'with': 1 };
+
+ function echoChar(c) {
+ if (c == '<')
+ result += '<';
+ else if (c == '>')
+ result += '>';
+ else if (c == '&')
+ result += '&';
+ else if (c == '\t')
+ result += ' ';
+ else
+ result += c;
+ }
+
+ function isDigit(number) {
+ var string = "1234567890";
+ if (string.indexOf(number) != -1)
+ return true;
+ return false;
+ }
+
+ function isHex(hex) {
+ var string = "1234567890abcdefABCDEF";
+ if (string.indexOf(hex) != -1)
+ return true;
+ return false;
+ }
+
+ function isLetter(letter) {
+ var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (string.indexOf(letter) != -1)
+ return true;
+ return false;
+ }
+
+ var result = "";
+ var cPrev = "";
+ var c = "";
+ var cNext = "";
+ for (var i = 0; i < code.length; i++) {
+ cPrev = c;
+ c = code.charAt(i);
+ cNext = code.charAt(i + 1);
+
+ if (c == "/" && cNext == "*") {
+ result += "";
+ echoChar(c);
+ if (c == "\n")
+ result += "";
+ continue;
+ } else if (c == "/" && cNext == "/") {
+ result += "";
+ echoChar(c);
+ continue;
+ } else if (c == "\"" || c == "'") {
+ var instringtype = c;
+ var stringstart = i;
+ result += "";
+ echoChar(c);
+ for (i += 1; i < code.length; i++) {
+ c = code.charAt(i);
+ if (stringstart < (i - 1) && cPrev == instringtype && code.charAt(i - 2) != "\\")
+ break;
+ echoChar(c);
+ cPrev = c;
+ }
+ result += "";
+ echoChar(c);
+ continue;
+ } else if (c == "0" && cNext == "x" && (i == 0 || (!isLetter(cPrev) && !isDigit(cPrev)))) {
+ result += "";
+ echoChar(c);
+ echoChar(cNext);
+ for (i += 2; i < code.length; i++) {
+ c = code.charAt(i);
+ if (!isHex(c))
+ break;
+ echoChar(c);
+ }
+ result += "";
+ echoChar(c);
+ continue;
+ } else if ((isDigit(c) || ((c == "-" || c == ".") && isDigit(cNext))) && (i == 0 || (!isLetter(cPrev) && !isDigit(cPrev)))) {
+ result += "";
+ echoChar(c);
+ for (i += 1; i < code.length; i++) {
+ c = code.charAt(i);
+ if (!isDigit(c) && c != ".")
+ break;
+ echoChar(c);
+ }
+ result += "";
+ echoChar(c);
+ continue;
+ } else if (isLetter(c) && (i == 0 || !isLetter(cPrev))) {
+ var keyword = c;
+ var cj = "";
+ for (var j = i + 1; j < i + 12 && j < code.length; j++) {
+ cj = code.charAt(j);
+ if (!isLetter(cj))
+ break;
+ keyword += cj;
+ }
+
+ if (keywords[keyword]) {
+ var functionName = "";
+ var functionIsAnonymous = false;
+ if (keyword == "function") {
+ var functionKeywordOffset = 8;
+ for (var j = i + functionKeywordOffset; j < code.length; j++) {
+ cj = code.charAt(j);
+ if (cj == " ")
+ continue;
+ if (cj == "(")
+ break;
+ functionName += cj;
+ }
+
+ if (!functionName.length) {
+ functionIsAnonymous = true;
+ var functionAssignmentFound = false;
+ var functionNameStart = -1;
+ var functionNameEnd = -1;
+
+ for (var j = i - 1; j >= 0; j--) {
+ cj = code.charAt(j);
+ if (cj == ":" || cj == "=") {
+ functionAssignmentFound = true;
+ continue;
+ }
+
+ var curCharIsSpace = (cj == " " || cj == "\t" || cj == "\n");
+ if (functionAssignmentFound && functionNameEnd == -1 && !curCharIsSpace) {
+ functionNameEnd = j + 1;
+ } else if (!functionAssignmentFound && !curCharIsSpace) {
+ break;
+ } else if (functionNameEnd != -1 && curCharIsSpace) {
+ functionNameStart = j;
+ break;
+ }
+ }
+
+ if (functionNameStart != -1 && functionNameEnd != -1)
+ functionName = code.substring(functionNameStart, functionNameEnd);
+ }
+
+ if (!functionName.length)
+ functionName = "function";
+
+ file.functionNames.push(functionName);
+ }
+
+ var fileIndex = filesLookup[file.url];
+
+ if (keyword == "function" && functionIsAnonymous)
+ result += "" + keyword + "";
+ else
+ result += "" + keyword + "";
+
+ if (functionName.length && !functionIsAnonymous) {
+ result += " " + functionName + "";
+ i += keyword.length + functionName.length;
+ } else
+ i += keyword.length - 1;
+
+ continue;
+ }
+ }
+
+ echoChar(c);
+ }
+
+ return result;
+}
+
+function navFilePrevious(element)
+{
+ if (element.disabled)
+ return;
+ var lastFile = previousFiles.pop();
+ if (currentFile != -1)
+ nextFiles.unshift(currentFile);
+ loadFile(lastFile, false);
+}
+
+function navFileNext(element)
+{
+ if (element.disabled)
+ return;
+ var lastFile = nextFiles.shift();
+ if (currentFile != -1)
+ previousFiles.push(currentFile);
+ loadFile(lastFile, false);
+}
+
+function updateFunctionStack()
+{
+ var stackframeTable = document.getElementById("stackframeTable");
+ stackframeTable.innerHTML = ""; // clear the content
+
+ currentStack = new Array();
+ var stack = DebuggerDocument.currentFunctionStack();
+ for(var i = 0; i < stack.length; i++) {
+ var tr = document.createElement("tr");
+ var td = document.createElement("td");
+ td.className = "stackNumber";
+ td.innerText = i;
+ tr.appendChild(td);
+
+ td = document.createElement("td");
+ td.innerText = stack[i];
+ tr.appendChild(td);
+ tr.addEventListener("click", selectStackFrame, true);
+
+ stackframeTable.appendChild(tr);
+
+ var frame = new ScriptCallFrame(stack[i], i, tr);
+ tr.callFrame = frame;
+ currentStack.push(frame);
+
+ if (i == 0) {
+ tr.addStyleClass("current");
+ frame.loadVariables();
+ currentCallFrame = frame;
+ }
+ }
+}
+
+function selectStackFrame(event)
+{
+ var stackframeTable = document.getElementById("stackframeTable");
+ var rows = stackframeTable.childNodes;
+ for (var i = 0; i < rows.length; i++)
+ rows[i].removeStyleClass("current");
+ this.addStyleClass("current");
+ this.callFrame.loadVariables();
+ currentCallFrame = this.callFrame;
+
+ if (frameLineNumberInfo = frameLineNumberStack[this.callFrame.index - 1])
+ jumpToLine(frameLineNumberInfo[0], frameLineNumberInfo[1]);
+ else if (this.callFrame.index == 0)
+ jumpToLine(lastStatement[0], lastStatement[1]);
+}
+
+function selectVariable(event)
+{
+ var variablesTable = document.getElementById("variablesTable");
+ var rows = variablesTable.childNodes;
+ for (var i = 0; i < rows.length; i++)
+ rows[i].removeStyleClass("current");
+ this.addStyleClass("current");
+}
+
+function switchFunction(index, shouldResetPopup)
+{
+ if (shouldResetPopup === undefined) shouldResetPopup = false;
+ var sourcesFrame = window.frames['sourcesFrame'];
+
+ if (shouldResetPopup || index == 0) {
+ document.getElementById("functionPopupButtonContent").innerHTML = '<No selected symbol>';
+ return;
+ }
+
+ var functionSelect = document.getElementById("functions");
+ var selectedFunction = functionSelect.childNodes[index];
+ var selection = sourcesFrame.getSelection();
+ var currentFunction = selectedFunction.value;
+ var currentFunctionElement = sourcesFrame.contentDocument.getElementById(currentFunction);
+
+ functionSelect.blur();
+ sourcesFrame.focus();
+ selection.setBaseAndExtent(currentFunctionElement, 0, currentFunctionElement, 1);
+ sourcesFrame.location.hash = "#function-" + selectedFunction.value;
+ document.getElementById("functionPopupButtonContent").innerText = selectedFunction.innerText;
+}
+
+function loadFile(fileIndex, manageNavLists)
+{
+ var file = files[fileIndex];
+ if (!file)
+ return;
+
+ if (currentFile != -1 && files[currentFile] && files[currentFile].element)
+ files[currentFile].element.style.display = "none";
+
+ if (!file.loaded) {
+ var sourcesDocument = document.getElementById("sources").contentDocument;
+ var sourcesDiv = sourcesDocument.body;
+ var sourceDiv = sourcesDocument.createElement("div");
+ sourceDiv.id = "file" + fileIndex;
+ sourcesDiv.appendChild(sourceDiv);
+ file.element = sourceDiv;
+
+ var table = sourcesDocument.createElement("table");
+ sourceDiv.appendChild(table);
+
+ var normalizedSource = file.source.replace(/\r\n|\r/g, "\n"); // normalize line endings
+ var lines = syntaxHighlight(normalizedSource, file).split("\n");
+ for( var i = 0; i < lines.length; i++ ) {
+ var tr = sourcesDocument.createElement("tr");
+ var td = sourcesDocument.createElement("td");
+ td.className = "gutter";
+ td.title = (i + 1);
+ td.addEventListener("click", breakpointAction, true);
+ td.addEventListener("dblclick", function(event) { toggleBreakpointEditorOnLine(event.target.title); }, true);
+ td.addEventListener("mousedown", moveBreakPoint, true);
+ tr.appendChild(td);
+
+ td = sourcesDocument.createElement("td");
+ td.className = "source";
+ td.innerHTML = (lines[i].length ? lines[i] : " ");
+ tr.appendChild(td);
+ table.appendChild(tr);
+ }
+
+ file.loaded = true;
+ }
+
+ file.element.style.removeProperty("display");
+
+ document.getElementById("filesPopupButtonContent").innerText = (file.url ? file.url : "(unknown script)");
+
+ var filesSelect = document.getElementById("files");
+ for (var i = 0; i < filesSelect.childNodes.length; i++) {
+ if (filesSelect.childNodes[i].value == fileIndex) {
+ filesSelect.selectedIndex = i;
+ break;
+ }
+ }
+
+ // Populate the function names pop-up
+ if (file.functionNames.length > 0) {
+ var functionSelect = document.getElementById("functions");
+ var functionOption = document.createElement("option");
+
+ document.getElementById("functionNamesPopup").style.display = "inline";
+ switchFunction(0, true);
+
+ functionSelect.removeChildren();
+ functionOption.value = null;
+ functionOption.text = "";
+ functionSelect.appendChild(functionOption);
+
+ for (var i = 0; i < file.functionNames.length; i++) {
+ functionOption = document.createElement("option");
+ functionOption.value = fileIndex + "-" + (i+1);
+ functionOption.text = file.functionNames[i] + "()";
+ functionSelect.appendChild(functionOption);
+ }
+ } else
+ document.getElementById("functionNamesPopup").style.display = "none";
+
+ if (manageNavLists) {
+ nextFiles = new Array();
+ if (currentFile != -1)
+ previousFiles.push(currentFile);
+ }
+
+ document.getElementById("navFileLeftButton").disabled = (previousFiles.length == 0);
+ document.getElementById("navFileRightButton").disabled = (nextFiles.length == 0);
+
+ //Remember and recall scroll position for current file and file we just loaded
+ var frameBody = document.getElementById("sources").contentDocument.body;
+ if (currentFile != -1)
+ files[currentFile].scrollPosition = frameBody.scrollTop;
+ frameBody.scrollTop = file.scrollPosition;
+ frameBody.scrollLeft = 0;
+
+ currentFile = fileIndex;
+}
+
+function updateFileSource(source, url, force)
+{
+ var fileIndex = filesLookup[url];
+ if (!fileIndex || !source.length)
+ return;
+
+ var file = files[fileIndex];
+ if (force || file.source.length != source.length || file.source != source) {
+ file.source = source;
+ file.loaded = false;
+
+ if (file.element) {
+ file.element.parentNode.removeChild(file.element);
+ file.element = null;
+ }
+
+ if (currentFile == fileIndex)
+ loadFile(fileIndex, false);
+ }
+}
+
+/**
+* ParsedURL - this object chops up full URL into two parts:
+ * 1) The domain: everything from http:// to the end of the domain name
+ * 2) The relative path: everything after the domain
+ *
+ * @param string url URL to be processed
+ */
+function ParsedURL(url)
+{
+ // Since we're getting the URL from the browser, we're safe to assume the URL is already well formatted
+ // and so there is no need for more sophisticated regular expression here
+ var url_parts = ((url.substring(0,4)).toLowerCase() == "file") ? url.match(/(file:[\/]{2,3}(\w|\.|-|_|\/)+)\/(.*)/) : url.match(/(http[s]?:\/\/(www)?\.?(\w|\.|-)+\w(:\d{1,5})?)\/?(.*)/);
+ // the domain here is considered the whole http://www.example.org:8000 or file:///Users/user/folder/file.htm string for display purposes
+ this.domain = url_parts[1];
+ // the relative path is everything following the domain
+ this.relativePath = (url_parts[5] === undefined) ? "/" + url_parts[3] : "/" + url_parts[5];
+}
+
+/**
+* SiteBrowser - modifies the file tree via DOM as new files are being open
+ *
+ */
+function SiteBrowser()
+{
+ var fileBrowser = document.getElementById("filesBrowserSites");
+
+ this.addURL = function add(url, fileIndex)
+ {
+ var parsedURL = new ParsedURL(url);
+ var divs = fileBrowser.getElementsByTagName("div");
+
+ if (divs.length == 0) {
+ addNewDomain(parsedURL, fileIndex);
+ } else {
+ var isNew = true;
+ for (var i = 0; i < divs.length; i++) {
+ if (divs[i].id == parsedURL.domain) {
+ var uls = divs[i].getElementsByTagName("ul");
+ var ul = (uls.length > 0) ? uls[0] : document.createElement("ul");
+ var li = document.createElement("li");
+
+ li.id = fileIndex;
+ li.addEventListener("click", fileBrowserMouseEvents, false);
+ li.title = li.innerText = parsedURL.relativePath ? parsedURL.relativePath : "/";
+ ul.appendChild(li);
+ isNew = false;
+ break;
+ }
+ }
+ if (isNew) {
+ addNewDomain(parsedURL, fileIndex);
+ }
+ }
+ }
+
+ this.selectInitialFile = function sf()
+ {
+ if (currentFile == -1)
+ document.getElementById("1").className = "active";
+ }
+
+ function addNewDomain(parsedURL, fileIndex)
+ {
+ var div = document.createElement("div");
+ var ul = document.createElement("ul");
+ var li = document.createElement("li");
+
+ div.id = div.innerText = div.title = parsedURL.domain;
+ div.addEventListener("click", fileBrowserMouseEvents, false);
+ // Maybe we can add some roll-overs here...
+ //div.addEventListener("mouseover", fileBrowserMouseEvents, false);
+ //div.addEventListener("mouseout", fileBrowserMouseEvents, false);
+ li.id = fileIndex;
+ li.addEventListener("click", fileBrowserMouseEvents, false);
+ li.title = li.innerText = parsedURL.relativePath ? parsedURL.relativePath : "/";
+ ul.appendChild(li);
+ div.appendChild(ul);
+ fileBrowser.appendChild(div);
+ }
+
+ function removeFile(fileIndex)
+ {
+ var theFile = document.getElementById(fileIndex);
+ // If we are removing the last file from its site, go ahead and remove the whole site
+ if (theFile.parentNode.childNodes.length < 2) {
+ var theSite = theFile.parentNode.parentNode;
+ theSite.removeChildren();
+ theSite.parentNode.removeChild(theSite);
+ }
+ else
+ theFile.parentNode.removeChild(theFile);
+ }
+}
+
+function fileBrowserMouseEvents(event)
+{
+ switch (event.type)
+ {
+ case "click":
+ // If we clicked on a site, collapse/expand it, if on a file, display it. Since we're only capturing this
+ // event from either a DIV or LI element, we don't have to worry about any ambiguity
+ (event.target.nodeName.toUpperCase() == "DIV") ? toggleCollapseSite(event) : fileClicked(event.target.id);
+ break;
+ }
+}
+
+function fileClicked(fileId, shouldLoadFile)
+{
+ if (shouldLoadFile === undefined)
+ shouldLoadFile = true;
+ if (currentFile != -1)
+ document.getElementById(currentFile).className = "passive";
+ document.getElementById(fileId).className = "active";
+ if (shouldLoadFile)
+ loadFile(fileId, false);
+}
+
+function toggleCollapseSite(event)
+{
+ var thisSite = document.getElementById(event.target.id);
+ var siteFiles = thisSite.getElementsByTagName("ul");
+
+ if (siteFiles[0].style.display == "block" || !siteFiles[0].style.display) {
+ siteFiles[0].style.display = "none";
+ thisSite.className = "collapsed";
+ } else {
+ siteFiles[0].style.display = "block";
+ thisSite.className = "expanded";
+ }
+}
+
+function didParseScript(source, fileSource, url, sourceId, baseLineNumber)
+{
+ var fileIndex = filesLookup[url];
+ var file = files[fileIndex];
+ var firstLoad = false;
+
+ if (!fileIndex || !file) {
+ fileIndex = files.length + 1;
+ if (url.length)
+ filesLookup[url] = fileIndex;
+
+ file = new Object();
+ file.scripts = new Array();
+ file.breakpoints = new Array();
+ file.functionNames = new Array();
+ file.source = (fileSource.length ? fileSource : source);
+ file.url = (url.length ? url : null);
+ file.loaded = false;
+
+ files[fileIndex] = file;
+
+ var filesSelect = document.getElementById("files");
+ var option = document.createElement("option");
+ files[fileIndex].menuOption = option;
+ option.value = fileIndex;
+ option.text = (file.url ? file.url : "(unknown script)");
+ filesSelect.appendChild(option);
+
+ var siteBrowser = new SiteBrowser();
+ siteBrowser.addURL(file.url, fileIndex);
+ siteBrowser.selectInitialFile();
+
+ firstLoad = true;
+ }
+
+ var sourceObj = new Object();
+ sourceObj.file = fileIndex;
+ sourceObj.baseLineNumber = baseLineNumber;
+ file.scripts.push(sourceId);
+ scripts[sourceId] = sourceObj;
+
+ if (!firstLoad)
+ updateFileSource((fileSource.length ? fileSource : source), url, false);
+
+ if (currentFile == -1)
+ loadFile(fileIndex, false);
+}
+
+function jumpToLine(sourceId, line)
+{
+ var script = scripts[sourceId];
+ if (line <= 0 || !script)
+ return;
+
+ var file = files[script.file];
+ if (!file)
+ return;
+
+ if (currentFile != script.file)
+ loadFile(script.file, true);
+ if (currentRow)
+ currentRow.removeStyleClass("current");
+ if (!file.element)
+ return;
+ if (line > file.element.firstChild.childNodes.length)
+ return;
+
+ currentRow = file.element.firstChild.childNodes.item(line - 1);
+ if (!currentRow)
+ return;
+
+ currentRow.addStyleClass("current");
+
+ var sourcesDiv = document.getElementById("sources");
+ var sourcesDocument = document.getElementById("sources").contentDocument;
+ var parent = sourcesDocument.body;
+ var offset = totalOffsetTop(currentRow, parent);
+ if (offset < (parent.scrollTop + 20) || offset > (parent.scrollTop + sourcesDiv.clientHeight - 20))
+ parent.scrollTop = totalOffsetTop(currentRow, parent) - (sourcesDiv.clientHeight / 2) + 10;
+}
+
+function willExecuteStatement(sourceId, line, fromLeavingFrame)
+{
+ var script = scripts[sourceId];
+ if (line <= 0 || !script)
+ return;
+
+ var file = files[script.file];
+ if (!file)
+ return;
+
+ lastStatement = [sourceId, line];
+
+ var breakpoint = file.breakpoints[line];
+
+ var shouldBreak = false;
+
+ if (breakpoint && breakpoint.enabled) {
+ switch(breakpoint.type) {
+ case 0:
+ shouldBreak = (breakpoint.value == "break" || DebuggerDocument.evaluateScript(breakpoint.value, 0) == 1);
+ if (shouldBreak)
+ breakpoint.hitcount++;
+ break;
+ case 1:
+ var message = "Hit breakpoint on line " + line;
+ if (breakpoint.value != "break")
+ message = DebuggerDocument.evaluateScript(breakpoint.value, 0);
+ if (consoleWindow)
+ consoleWindow.appendMessage("", message);
+ breakpoint.hitcount++;
+ break;
+ }
+ var editor = breakpoint.editor;
+ var counter = null;
+ if (editor)
+ counter = breakpoint.editor.query('.//span[@class="hitCounter"]');
+ if (counter)
+ counter.innerText = breakpoint.hitcount;
+ }
+
+ if (pauseOnNextStatement || shouldBreak || (steppingOver && !steppingStack)) {
+ pause();
+ pauseOnNextStatement = false;
+ pausedWhileLeavingFrame = fromLeavingFrame || false;
+ }
+
+ if (isPaused) {
+ updateFunctionStack();
+ jumpToLine(sourceId, line);
+ }
+}
+
+function didEnterCallFrame(sourceId, line)
+{
+ if (steppingOver || steppingOut)
+ steppingStack++;
+
+ if (lastStatement)
+ frameLineNumberStack.unshift(lastStatement);
+ willExecuteStatement(sourceId, line);
+}
+
+function willLeaveCallFrame(sourceId, line)
+{
+ if (line <= 0)
+ resume();
+ willExecuteStatement(sourceId, line, true);
+ frameLineNumberStack.shift();
+ if (!steppingStack)
+ steppingOver = false;
+ if (steppingOut && !steppingStack) {
+ steppingOut = false;
+ pauseOnNextStatement = true;
+ }
+ if ((steppingOver || steppingOut) && steppingStack >= 1)
+ steppingStack--;
+}
+
+function exceptionWasRaised(sourceId, line)
+{
+ pause();
+ updateFunctionStack();
+ jumpToLine(sourceId, line);
+}
+
+function showConsoleWindow()
+{
+ if (!consoleWindow)
+ consoleWindow = window.open("console.html", "console", "top=200, left=200, width=500, height=300, toolbar=yes, resizable=yes");
+ else
+ consoleWindow.focus();
+}
+
+function closeFile(fileIndex)
+{
+ if (fileIndex != -1) {
+ currentFile = -1;
+ var file = files[fileIndex];
+ var sourcesDocument = document.getElementById("sources").contentDocument;
+ // Clean up our file's content
+ sourcesDocument.getElementById("file" + fileIndex).removeChildren();
+ // Remove the file from the open files pool
+ delete sourcesDocument.getElementById("file" + fileIndex);
+
+ var filesSelect = document.getElementById("files");
+ // Select the next loaded file. If we're at the end of the list, loop back to beginning.
+ var nextSelectedFile = (filesSelect.selectedIndex + 1 >= filesSelect.options.length) ? 0 : filesSelect.selectedIndex;
+ // Remove the file from file lists
+ filesSelect.options[filesSelect.selectedIndex] = null;
+ SiteBrowser.removeFile(fileIndex);
+ delete files[fileIndex];
+
+ // Clean up the function list
+ document.getElementById("functions").removeChildren();
+
+ // Display appropriate place-holders, if we closed all files
+ if (filesSelect.options.length < 1) {
+ document.getElementById("filesPopupButtonContent").innerHTML = "<No files loaded>";
+ document.getElementById("functionNamesPopup").style.display = "none";
+ }
+ else
+ switchFile(nextSelectedFile);
+ }
+}
+
+function closeCurrentFile()
+{
+ closeFile(currentFile);
+}