Index: chrome_frame/tools/test/reference_build/chrome/resources/inspector/SourceFrame.js |
=================================================================== |
--- chrome_frame/tools/test/reference_build/chrome/resources/inspector/SourceFrame.js (revision 0) |
+++ chrome_frame/tools/test/reference_build/chrome/resources/inspector/SourceFrame.js (revision 0) |
@@ -0,0 +1,906 @@ |
+/* |
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
+ * |
+ * 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. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR |
+ * 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. |
+ */ |
+ |
+WebInspector.SourceFrame = function(element, addBreakpointDelegate) |
+{ |
+ this.messages = []; |
+ this.breakpoints = []; |
+ this._shortcuts = {}; |
+ |
+ this.addBreakpointDelegate = addBreakpointDelegate; |
+ |
+ this.element = element || document.createElement("iframe"); |
+ this.element.addStyleClass("source-view-frame"); |
+ this.element.setAttribute("viewsource", "true"); |
+ |
+ this.element.addEventListener("load", this._loaded.bind(this), false); |
+} |
+ |
+WebInspector.SourceFrame.prototype = { |
+ get executionLine() |
+ { |
+ return this._executionLine; |
+ }, |
+ |
+ set executionLine(x) |
+ { |
+ if (this._executionLine === x) |
+ return; |
+ |
+ var previousLine = this._executionLine; |
+ this._executionLine = x; |
+ |
+ this._updateExecutionLine(previousLine); |
+ }, |
+ |
+ get autoSizesToFitContentHeight() |
+ { |
+ return this._autoSizesToFitContentHeight; |
+ }, |
+ |
+ set autoSizesToFitContentHeight(x) |
+ { |
+ if (this._autoSizesToFitContentHeight === x) |
+ return; |
+ |
+ this._autoSizesToFitContentHeight = x; |
+ |
+ if (this._autoSizesToFitContentHeight) { |
+ this._windowResizeListener = this._windowResized.bind(this); |
+ window.addEventListener("resize", this._windowResizeListener, false); |
+ this.sizeToFitContentHeight(); |
+ } else { |
+ this.element.style.removeProperty("height"); |
+ if (this.element.contentDocument) |
+ this.element.contentDocument.body.removeStyleClass("webkit-height-sized-to-fit"); |
+ window.removeEventListener("resize", this._windowResizeListener, false); |
+ delete this._windowResizeListener; |
+ } |
+ }, |
+ |
+ sourceRow: function(lineNumber) |
+ { |
+ if (!lineNumber || !this.element.contentDocument) |
+ return; |
+ |
+ var table = this.element.contentDocument.getElementsByTagName("table")[0]; |
+ if (!table) |
+ return; |
+ |
+ var rows = table.rows; |
+ |
+ // Line numbers are a 1-based index, but the rows collection is 0-based. |
+ --lineNumber; |
+ |
+ return rows[lineNumber]; |
+ }, |
+ |
+ lineNumberForSourceRow: function(sourceRow) |
+ { |
+ // Line numbers are a 1-based index, but the rows collection is 0-based. |
+ var lineNumber = 0; |
+ while (sourceRow) { |
+ ++lineNumber; |
+ sourceRow = sourceRow.previousSibling; |
+ } |
+ |
+ return lineNumber; |
+ }, |
+ |
+ revealLine: function(lineNumber) |
+ { |
+ if (!this._isContentLoaded()) { |
+ this._lineNumberToReveal = lineNumber; |
+ return; |
+ } |
+ |
+ var row = this.sourceRow(lineNumber); |
+ if (row) |
+ row.scrollIntoViewIfNeeded(true); |
+ }, |
+ |
+ addBreakpoint: function(breakpoint) |
+ { |
+ this.breakpoints.push(breakpoint); |
+ breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this); |
+ breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this); |
+ this._addBreakpointToSource(breakpoint); |
+ }, |
+ |
+ removeBreakpoint: function(breakpoint) |
+ { |
+ this.breakpoints.remove(breakpoint); |
+ breakpoint.removeEventListener("enabled", null, this); |
+ breakpoint.removeEventListener("disabled", null, this); |
+ this._removeBreakpointFromSource(breakpoint); |
+ }, |
+ |
+ addMessage: function(msg) |
+ { |
+ // Don't add the message if there is no message or valid line or if the msg isn't an error or warning. |
+ if (!msg.message || msg.line <= 0 || !msg.isErrorOrWarning()) |
+ return; |
+ this.messages.push(msg); |
+ this._addMessageToSource(msg); |
+ }, |
+ |
+ clearMessages: function() |
+ { |
+ this.messages = []; |
+ |
+ if (!this.element.contentDocument) |
+ return; |
+ |
+ var bubbles = this.element.contentDocument.querySelectorAll(".webkit-html-message-bubble"); |
+ if (!bubbles) |
+ return; |
+ |
+ for (var i = 0; i < bubbles.length; ++i) { |
+ var bubble = bubbles[i]; |
+ bubble.parentNode.removeChild(bubble); |
+ } |
+ }, |
+ |
+ sizeToFitContentHeight: function() |
+ { |
+ if (this.element.contentDocument) { |
+ this.element.style.setProperty("height", this.element.contentDocument.body.offsetHeight + "px"); |
+ this.element.contentDocument.body.addStyleClass("webkit-height-sized-to-fit"); |
+ } |
+ }, |
+ |
+ _highlightLineEnds: function(event) |
+ { |
+ event.target.parentNode.removeStyleClass("webkit-highlighted-line"); |
+ }, |
+ |
+ highlightLine: function(lineNumber) |
+ { |
+ if (!this._isContentLoaded()) { |
+ this._lineNumberToHighlight = lineNumber; |
+ return; |
+ } |
+ |
+ var sourceRow = this.sourceRow(lineNumber); |
+ if (!sourceRow) |
+ return; |
+ var line = sourceRow.getElementsByClassName('webkit-line-content')[0]; |
+ // Trick to reset the animation if the user clicks on the same link |
+ // Using a timeout to avoid coalesced style updates |
+ line.style.setProperty("-webkit-animation-name", "none"); |
+ setTimeout(function () { |
+ line.style.removeProperty("-webkit-animation-name"); |
+ sourceRow.addStyleClass("webkit-highlighted-line"); |
+ }, 0); |
+ }, |
+ |
+ _loaded: function() |
+ { |
+ WebInspector.addMainEventListeners(this.element.contentDocument); |
+ this.element.contentDocument.addEventListener("contextmenu", this._documentContextMenu.bind(this), true); |
+ this.element.contentDocument.addEventListener("mousedown", this._documentMouseDown.bind(this), true); |
+ this.element.contentDocument.addEventListener("keydown", this._documentKeyDown.bind(this), true); |
+ this.element.contentDocument.addEventListener("keyup", WebInspector.documentKeyUp.bind(WebInspector), true); |
+ this.element.contentDocument.addEventListener("webkitAnimationEnd", this._highlightLineEnds.bind(this), false); |
+ |
+ // Register 'eval' shortcut. |
+ var isMac = InspectorController.platform().indexOf("mac-") === 0; |
+ var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl; |
+ var shortcut = WebInspector.KeyboardShortcut.makeKey(69 /* 'E' */, platformSpecificModifier | WebInspector.KeyboardShortcut.Modifiers.Shift); |
+ this._shortcuts[shortcut] = this._evalSelectionInCallFrame.bind(this); |
+ |
+ var headElement = this.element.contentDocument.getElementsByTagName("head")[0]; |
+ if (!headElement) { |
+ headElement = this.element.contentDocument.createElement("head"); |
+ this.element.contentDocument.documentElement.insertBefore(headElement, this.element.contentDocument.documentElement.firstChild); |
+ } |
+ |
+ var styleElement = this.element.contentDocument.createElement("style"); |
+ headElement.appendChild(styleElement); |
+ |
+ // Add these style rules here since they are specific to the Inspector. They also behave oddly and not |
+ // all properties apply if added to view-source.css (becuase it is a user agent sheet.) |
+ var styleText = ".webkit-line-number { background-repeat: no-repeat; background-position: right 1px; }\n"; |
+ styleText += ".webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(program-counter); }\n"; |
+ |
+ styleText += ".webkit-breakpoint .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint); }\n"; |
+ styleText += ".webkit-breakpoint-disabled .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled); }\n"; |
+ styleText += ".webkit-breakpoint.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-program-counter); }\n"; |
+ styleText += ".webkit-breakpoint-disabled.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-program-counter); }\n"; |
+ |
+ styleText += ".webkit-breakpoint.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-conditional); }\n"; |
+ styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled-conditional); }\n"; |
+ styleText += ".webkit-breakpoint.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-conditional-program-counter); }\n"; |
+ styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-conditional-program-counter); }\n"; |
+ |
+ styleText += ".webkit-execution-line .webkit-line-content { background-color: rgb(171, 191, 254); outline: 1px solid rgb(64, 115, 244); }\n"; |
+ styleText += ".webkit-height-sized-to-fit { overflow-y: hidden }\n"; |
+ styleText += ".webkit-line-content { background-color: white; }\n"; |
+ styleText += "@-webkit-keyframes fadeout {from {background-color: rgb(255, 255, 120);} to { background-color: white;}}\n"; |
+ styleText += ".webkit-highlighted-line .webkit-line-content { background-color: rgb(255, 255, 120); -webkit-animation: 'fadeout' 2s 500ms}\n"; |
+ styleText += ".webkit-javascript-comment { color: rgb(0, 116, 0); }\n"; |
+ styleText += ".webkit-javascript-keyword { color: rgb(170, 13, 145); }\n"; |
+ styleText += ".webkit-javascript-number { color: rgb(28, 0, 207); }\n"; |
+ styleText += ".webkit-javascript-string, .webkit-javascript-regexp { color: rgb(196, 26, 22); }\n"; |
+ |
+ // TODO: Move these styles into inspector.css once https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed and popup moved into the top frame. |
+ styleText += ".popup-content { position: absolute; z-index: 10000; padding: 4px; background-color: rgb(203, 226, 255); -webkit-border-radius: 7px; border: 2px solid rgb(169, 172, 203); }"; |
+ styleText += ".popup-glasspane { position: absolute; top: 0; left: 0; height: 100%; width: 100%; opacity: 0; z-index: 9900; }"; |
+ styleText += ".popup-message { background-color: transparent; font-family: Lucida Grande, sans-serif; font-weight: normal; font-size: 11px; text-align: left; text-shadow: none; color: rgb(85, 85, 85); cursor: default; margin: 0 0 2px 0; }"; |
+ styleText += ".popup-content.breakpoint-condition { width: 90%; }"; |
+ styleText += ".popup-content input#bp-condition { font-family: monospace; margin: 0; border: 1px inset rgb(190, 190, 190) !important; width: 100%; box-shadow: none !important; outline: none !important; -webkit-user-modify: read-write; }"; |
+ // This class is already in inspector.css |
+ styleText += ".hidden { display: none !important; }"; |
+ |
+ styleElement.textContent = styleText; |
+ |
+ this._needsProgramCounterImage = true; |
+ this._needsBreakpointImages = true; |
+ |
+ this.element.contentWindow.Element.prototype.addStyleClass = Element.prototype.addStyleClass; |
+ this.element.contentWindow.Element.prototype.removeStyleClass = Element.prototype.removeStyleClass; |
+ this.element.contentWindow.Element.prototype.positionAt = Element.prototype.positionAt; |
+ this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses; |
+ this.element.contentWindow.Element.prototype.hasStyleClass = Element.prototype.hasStyleClass; |
+ this.element.contentWindow.Element.prototype.pageOffsetRelativeToWindow = Element.prototype.pageOffsetRelativeToWindow; |
+ this.element.contentWindow.Element.prototype.__defineGetter__("totalOffsetLeft", Element.prototype.__lookupGetter__("totalOffsetLeft")); |
+ this.element.contentWindow.Element.prototype.__defineGetter__("totalOffsetTop", Element.prototype.__lookupGetter__("totalOffsetTop")); |
+ this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeName = Node.prototype.enclosingNodeOrSelfWithNodeName; |
+ this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = Node.prototype.enclosingNodeOrSelfWithNodeNameInArray; |
+ |
+ this._addExistingMessagesToSource(); |
+ this._addExistingBreakpointsToSource(); |
+ this._updateExecutionLine(); |
+ if (this._executionLine) |
+ this.revealLine(this._executionLine); |
+ |
+ if (this.autoSizesToFitContentHeight) |
+ this.sizeToFitContentHeight(); |
+ |
+ if (this._lineNumberToReveal) { |
+ this.revealLine(this._lineNumberToReveal); |
+ delete this._lineNumberToReveal; |
+ } |
+ |
+ if (this._lineNumberToHighlight) { |
+ this.highlightLine(this._lineNumberToHighlight); |
+ delete this._lineNumberToHighlight; |
+ } |
+ |
+ this.dispatchEventToListeners("content loaded"); |
+ }, |
+ |
+ _isContentLoaded: function() { |
+ var doc = this.element.contentDocument; |
+ return doc && doc.getElementsByTagName("table")[0]; |
+ }, |
+ |
+ _windowResized: function(event) |
+ { |
+ if (!this._autoSizesToFitContentHeight) |
+ return; |
+ this.sizeToFitContentHeight(); |
+ }, |
+ |
+ _documentContextMenu: function(event) |
+ { |
+ if (!event.target.hasStyleClass("webkit-line-number")) |
+ return; |
+ var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr"); |
+ if (!sourceRow._breakpointObject && this.addBreakpointDelegate) |
+ this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow)); |
+ |
+ var breakpoint = sourceRow._breakpointObject; |
+ if (!breakpoint) |
+ return; |
+ |
+ this._editBreakpointCondition(event.target, sourceRow, breakpoint); |
+ event.preventDefault(); |
+ }, |
+ |
+ _documentMouseDown: function(event) |
+ { |
+ if (!event.target.hasStyleClass("webkit-line-number")) |
+ return; |
+ if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) |
+ return; |
+ var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr"); |
+ if (sourceRow._breakpointObject && sourceRow._breakpointObject.enabled) |
+ sourceRow._breakpointObject.enabled = false; |
+ else if (sourceRow._breakpointObject) |
+ WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointObject); |
+ else if (this.addBreakpointDelegate) |
+ this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow)); |
+ }, |
+ |
+ _editBreakpointCondition: function(eventTarget, sourceRow, breakpoint) |
+ { |
+ // TODO: Migrate the popup to the top-level document and remove the blur listener from conditionElement once https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed. |
+ var popupDocument = this.element.contentDocument; |
+ this._showBreakpointConditionPopup(eventTarget, breakpoint.line, popupDocument); |
+ |
+ function committed(element, newText) |
+ { |
+ breakpoint.condition = newText; |
+ if (breakpoint.condition) |
+ sourceRow.addStyleClass("webkit-breakpoint-conditional"); |
+ else |
+ sourceRow.removeStyleClass("webkit-breakpoint-conditional"); |
+ dismissed.call(this); |
+ } |
+ |
+ function dismissed() |
+ { |
+ this._popup.hide(); |
+ delete this._conditionEditorElement; |
+ } |
+ |
+ var dismissedHandler = dismissed.bind(this); |
+ this._conditionEditorElement.addEventListener("blur", dismissedHandler, false); |
+ |
+ WebInspector.startEditing(this._conditionEditorElement, committed.bind(this), dismissedHandler); |
+ this._conditionEditorElement.value = breakpoint.condition; |
+ this._conditionEditorElement.select(); |
+ }, |
+ |
+ _showBreakpointConditionPopup: function(clickedElement, lineNumber, popupDocument) |
+ { |
+ var popupContentElement = this._createPopupElement(lineNumber, popupDocument); |
+ var lineElement = clickedElement.enclosingNodeOrSelfWithNodeName("td").nextSibling; |
+ if (this._popup) { |
+ this._popup.hide(); |
+ this._popup.element = popupContentElement; |
+ } else { |
+ this._popup = new WebInspector.Popup(popupContentElement); |
+ this._popup.autoHide = true; |
+ } |
+ this._popup.anchor = lineElement; |
+ this._popup.show(); |
+ }, |
+ |
+ _createPopupElement: function(lineNumber, popupDocument) |
+ { |
+ var popupContentElement = popupDocument.createElement("div"); |
+ popupContentElement.className = "popup-content breakpoint-condition"; |
+ |
+ var labelElement = document.createElement("label"); |
+ labelElement.className = "popup-message"; |
+ labelElement.htmlFor = "bp-condition"; |
+ labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber))); |
+ popupContentElement.appendChild(labelElement); |
+ |
+ var editorElement = document.createElement("input"); |
+ editorElement.id = "bp-condition"; |
+ editorElement.type = "text" |
+ popupContentElement.appendChild(editorElement); |
+ this._conditionEditorElement = editorElement; |
+ |
+ return popupContentElement; |
+ }, |
+ |
+ _documentKeyDown: function(event) |
+ { |
+ var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); |
+ var handler = this._shortcuts[shortcut]; |
+ if (handler) { |
+ handler(event); |
+ event.preventDefault(); |
+ } else { |
+ WebInspector.documentKeyDown(event); |
+ } |
+ }, |
+ |
+ _evalSelectionInCallFrame: function(event) |
+ { |
+ if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) |
+ return; |
+ |
+ var selection = this.element.contentWindow.getSelection(); |
+ if (!selection.rangeCount) |
+ return; |
+ |
+ var expression = selection.getRangeAt(0).toString().trimWhitespace(); |
+ WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, function(result, exception) { |
+ WebInspector.showConsole(); |
+ var commandMessage = new WebInspector.ConsoleCommand(expression); |
+ WebInspector.console.addMessage(commandMessage); |
+ WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage)); |
+ }); |
+ }, |
+ |
+ _breakpointEnableChanged: function(event) |
+ { |
+ var breakpoint = event.target; |
+ var sourceRow = this.sourceRow(breakpoint.line); |
+ if (!sourceRow) |
+ return; |
+ |
+ sourceRow.addStyleClass("webkit-breakpoint"); |
+ |
+ if (breakpoint.enabled) |
+ sourceRow.removeStyleClass("webkit-breakpoint-disabled"); |
+ else |
+ sourceRow.addStyleClass("webkit-breakpoint-disabled"); |
+ }, |
+ |
+ _updateExecutionLine: function(previousLine) |
+ { |
+ if (previousLine) { |
+ var sourceRow = this.sourceRow(previousLine); |
+ if (sourceRow) |
+ sourceRow.removeStyleClass("webkit-execution-line"); |
+ } |
+ |
+ if (!this._executionLine) |
+ return; |
+ |
+ this._drawProgramCounterImageIfNeeded(); |
+ |
+ var sourceRow = this.sourceRow(this._executionLine); |
+ if (sourceRow) |
+ sourceRow.addStyleClass("webkit-execution-line"); |
+ }, |
+ |
+ _addExistingBreakpointsToSource: function() |
+ { |
+ var length = this.breakpoints.length; |
+ for (var i = 0; i < length; ++i) |
+ this._addBreakpointToSource(this.breakpoints[i]); |
+ }, |
+ |
+ _addBreakpointToSource: function(breakpoint) |
+ { |
+ var sourceRow = this.sourceRow(breakpoint.line); |
+ if (!sourceRow) |
+ return; |
+ |
+ breakpoint.sourceText = sourceRow.getElementsByClassName('webkit-line-content')[0].textContent; |
+ |
+ this._drawBreakpointImagesIfNeeded(); |
+ |
+ sourceRow._breakpointObject = breakpoint; |
+ |
+ sourceRow.addStyleClass("webkit-breakpoint"); |
+ if (!breakpoint.enabled) |
+ sourceRow.addStyleClass("webkit-breakpoint-disabled"); |
+ if (breakpoint.condition) |
+ sourceRow.addStyleClass("webkit-breakpoint-conditional"); |
+ }, |
+ |
+ _removeBreakpointFromSource: function(breakpoint) |
+ { |
+ var sourceRow = this.sourceRow(breakpoint.line); |
+ if (!sourceRow) |
+ return; |
+ |
+ delete sourceRow._breakpointObject; |
+ |
+ sourceRow.removeStyleClass("webkit-breakpoint"); |
+ sourceRow.removeStyleClass("webkit-breakpoint-disabled"); |
+ sourceRow.removeStyleClass("webkit-breakpoint-conditional"); |
+ }, |
+ |
+ _incrementMessageRepeatCount: function(msg, repeatDelta) |
+ { |
+ if (!msg._resourceMessageLineElement) |
+ return; |
+ |
+ if (!msg._resourceMessageRepeatCountElement) { |
+ var repeatedElement = document.createElement("span"); |
+ msg._resourceMessageLineElement.appendChild(repeatedElement); |
+ msg._resourceMessageRepeatCountElement = repeatedElement; |
+ } |
+ |
+ msg.repeatCount += repeatDelta; |
+ msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", msg.repeatCount); |
+ }, |
+ |
+ _addExistingMessagesToSource: function() |
+ { |
+ var length = this.messages.length; |
+ for (var i = 0; i < length; ++i) |
+ this._addMessageToSource(this.messages[i]); |
+ }, |
+ |
+ _addMessageToSource: function(msg) |
+ { |
+ var row = this.sourceRow(msg.line); |
+ if (!row) |
+ return; |
+ |
+ var cell = row.cells[1]; |
+ if (!cell) |
+ return; |
+ |
+ var messageBubbleElement = cell.lastChild; |
+ if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) { |
+ messageBubbleElement = this.element.contentDocument.createElement("div"); |
+ messageBubbleElement.className = "webkit-html-message-bubble"; |
+ cell.appendChild(messageBubbleElement); |
+ } |
+ |
+ if (!row.messages) |
+ row.messages = []; |
+ |
+ for (var i = 0; i < row.messages.length; ++i) { |
+ if (row.messages[i].isEqual(msg, true)) { |
+ this._incrementMessageRepeatCount(row.messages[i], msg.repeatDelta); |
+ return; |
+ } |
+ } |
+ |
+ row.messages.push(msg); |
+ |
+ var imageURL; |
+ switch (msg.level) { |
+ case WebInspector.ConsoleMessage.MessageLevel.Error: |
+ messageBubbleElement.addStyleClass("webkit-html-error-message"); |
+ imageURL = "Images/errorIcon.png"; |
+ break; |
+ case WebInspector.ConsoleMessage.MessageLevel.Warning: |
+ messageBubbleElement.addStyleClass("webkit-html-warning-message"); |
+ imageURL = "Images/warningIcon.png"; |
+ break; |
+ } |
+ |
+ var messageLineElement = this.element.contentDocument.createElement("div"); |
+ messageLineElement.className = "webkit-html-message-line"; |
+ messageBubbleElement.appendChild(messageLineElement); |
+ |
+ // Create the image element in the Inspector's document so we can use relative image URLs. |
+ var image = document.createElement("img"); |
+ image.src = imageURL; |
+ image.className = "webkit-html-message-icon"; |
+ |
+ // Adopt the image element since it wasn't created in element's contentDocument. |
+ image = this.element.contentDocument.adoptNode(image); |
+ messageLineElement.appendChild(image); |
+ messageLineElement.appendChild(this.element.contentDocument.createTextNode(msg.message)); |
+ |
+ msg._resourceMessageLineElement = messageLineElement; |
+ }, |
+ |
+ _drawProgramCounterInContext: function(ctx, glow) |
+ { |
+ if (glow) |
+ ctx.save(); |
+ |
+ ctx.beginPath(); |
+ ctx.moveTo(17, 2); |
+ ctx.lineTo(19, 2); |
+ ctx.lineTo(19, 0); |
+ ctx.lineTo(21, 0); |
+ ctx.lineTo(26, 5.5); |
+ ctx.lineTo(21, 11); |
+ ctx.lineTo(19, 11); |
+ ctx.lineTo(19, 9); |
+ ctx.lineTo(17, 9); |
+ ctx.closePath(); |
+ ctx.fillStyle = "rgb(142, 5, 4)"; |
+ |
+ if (glow) { |
+ ctx.shadowBlur = 4; |
+ ctx.shadowColor = "rgb(255, 255, 255)"; |
+ ctx.shadowOffsetX = -1; |
+ ctx.shadowOffsetY = 0; |
+ } |
+ |
+ ctx.fill(); |
+ ctx.fill(); // Fill twice to get a good shadow and darker anti-aliased pixels. |
+ |
+ if (glow) |
+ ctx.restore(); |
+ }, |
+ |
+ _drawProgramCounterImageIfNeeded: function() |
+ { |
+ if (!this._needsProgramCounterImage || !this.element.contentDocument) |
+ return; |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "program-counter", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ this._drawProgramCounterInContext(ctx, true); |
+ |
+ delete this._needsProgramCounterImage; |
+ }, |
+ |
+ _drawBreakpointImagesIfNeeded: function(conditional) |
+ { |
+ if (!this._needsBreakpointImages || !this.element.contentDocument) |
+ return; |
+ |
+ function drawBreakpoint(ctx, disabled, conditional) |
+ { |
+ ctx.beginPath(); |
+ ctx.moveTo(0, 2); |
+ ctx.lineTo(2, 0); |
+ ctx.lineTo(21, 0); |
+ ctx.lineTo(26, 5.5); |
+ ctx.lineTo(21, 11); |
+ ctx.lineTo(2, 11); |
+ ctx.lineTo(0, 9); |
+ ctx.closePath(); |
+ ctx.fillStyle = conditional ? "rgb(217, 142, 1)" : "rgb(1, 142, 217)"; |
+ ctx.strokeStyle = conditional ? "rgb(205, 103, 0)" : "rgb(0, 103, 205)"; |
+ ctx.lineWidth = 3; |
+ ctx.fill(); |
+ ctx.save(); |
+ ctx.clip(); |
+ ctx.stroke(); |
+ ctx.restore(); |
+ |
+ if (!disabled) |
+ return; |
+ |
+ ctx.save(); |
+ ctx.globalCompositeOperation = "destination-out"; |
+ ctx.fillStyle = "rgba(0, 0, 0, 0.5)"; |
+ ctx.fillRect(0, 0, 26, 11); |
+ ctx.restore(); |
+ } |
+ |
+ |
+ // Unconditional breakpoints. |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ drawBreakpoint(ctx); |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-program-counter", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ drawBreakpoint(ctx); |
+ ctx.clearRect(20, 0, 6, 11); |
+ this._drawProgramCounterInContext(ctx, true); |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ drawBreakpoint(ctx, true); |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-program-counter", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ drawBreakpoint(ctx, true); |
+ ctx.clearRect(20, 0, 6, 11); |
+ this._drawProgramCounterInContext(ctx, true); |
+ |
+ |
+ // Conditional breakpoints. |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-conditional", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ drawBreakpoint(ctx, false, true); |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-conditional-program-counter", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ drawBreakpoint(ctx, false, true); |
+ ctx.clearRect(20, 0, 6, 11); |
+ this._drawProgramCounterInContext(ctx, true); |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-conditional", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ drawBreakpoint(ctx, true, true); |
+ |
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-conditional-program-counter", 26, 11); |
+ ctx.clearRect(0, 0, 26, 11); |
+ drawBreakpoint(ctx, true, true); |
+ ctx.clearRect(20, 0, 6, 11); |
+ this._drawProgramCounterInContext(ctx, true); |
+ |
+ delete this._needsBreakpointImages; |
+ }, |
+ |
+ syntaxHighlightJavascript: function() |
+ { |
+ var table = this.element.contentDocument.getElementsByTagName("table")[0]; |
+ if (!table) |
+ return; |
+ |
+ function deleteContinueFlags(cell) |
+ { |
+ if (!cell) |
+ return; |
+ delete cell._commentContinues; |
+ delete cell._singleQuoteStringContinues; |
+ delete cell._doubleQuoteStringContinues; |
+ delete cell._regexpContinues; |
+ } |
+ |
+ function createSpan(content, className) |
+ { |
+ var span = document.createElement("span"); |
+ span.className = className; |
+ span.appendChild(document.createTextNode(content)); |
+ return span; |
+ } |
+ |
+ function generateFinder(regex, matchNumber, className) |
+ { |
+ return function(str) { |
+ var match = regex.exec(str); |
+ if (!match) |
+ return null; |
+ previousMatchLength = match[matchNumber].length; |
+ return createSpan(match[matchNumber], className); |
+ }; |
+ } |
+ |
+ var findNumber = generateFinder(/^(-?(\d+\.?\d*([eE][+-]\d+)?|0[xX]\h+|Infinity)|NaN)(?:\W|$)/, 1, "webkit-javascript-number"); |
+ var findKeyword = generateFinder(/^(null|true|false|break|case|catch|const|default|finally|for|instanceof|new|var|continue|function|return|void|delete|if|this|do|while|else|in|switch|throw|try|typeof|with|debugger|class|enum|export|extends|import|super|get|set)(?:\W|$)/, 1, "webkit-javascript-keyword"); |
+ var findSingleLineString = generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\]|\\.)*'/, 0, "webkit-javascript-string"); // " this quote keeps Xcode happy |
+ var findMultilineCommentStart = generateFinder(/^\/\*.*$/, 0, "webkit-javascript-comment"); |
+ var findMultilineCommentEnd = generateFinder(/^.*?\*\//, 0, "webkit-javascript-comment"); |
+ var findMultilineSingleQuoteStringStart = generateFinder(/^'(?:[^'\\]|\\.)*\\$/, 0, "webkit-javascript-string"); |
+ var findMultilineSingleQuoteStringEnd = generateFinder(/^(?:[^'\\]|\\.)*?'/, 0, "webkit-javascript-string"); |
+ var findMultilineDoubleQuoteStringStart = generateFinder(/^"(?:[^"\\]|\\.)*\\$/, 0, "webkit-javascript-string"); |
+ var findMultilineDoubleQuoteStringEnd = generateFinder(/^(?:[^"\\]|\\.)*?"/, 0, "webkit-javascript-string"); |
+ var findMultilineRegExpEnd = generateFinder(/^(?:[^\/\\]|\\.)*?\/([gim]{0,3})/, 0, "webkit-javascript-regexp"); |
+ var findSingleLineComment = generateFinder(/^\/\/.*|^\/\*.*?\*\//, 0, "webkit-javascript-comment"); |
+ |
+ function findMultilineRegExpStart(str) |
+ { |
+ var match = /^\/(?:[^\/\\]|\\.)*\\$/.exec(str); |
+ if (!match || !/\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[0])) |
+ return null; |
+ var node = createSpan(match[0], "webkit-javascript-regexp"); |
+ previousMatchLength = match[0].length; |
+ return node; |
+ } |
+ |
+ function findSingleLineRegExp(str) |
+ { |
+ var match = /^(\/(?:[^\/\\]|\\.)*\/([gim]{0,3}))(.?)/.exec(str); |
+ if (!match || !(match[2].length > 0 || /\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[1]) || /\.|;|,/.test(match[3]))) |
+ return null; |
+ var node = createSpan(match[1], "webkit-javascript-regexp"); |
+ previousMatchLength = match[1].length; |
+ return node; |
+ } |
+ |
+ function syntaxHighlightJavascriptLine(line, prevLine) |
+ { |
+ var messageBubble = line.lastChild; |
+ if (messageBubble && messageBubble.nodeType === Node.ELEMENT_NODE && messageBubble.hasStyleClass("webkit-html-message-bubble")) |
+ line.removeChild(messageBubble); |
+ else |
+ messageBubble = null; |
+ |
+ var code = line.textContent; |
+ |
+ while (line.firstChild) |
+ line.removeChild(line.firstChild); |
+ |
+ var token; |
+ var tmp = 0; |
+ var i = 0; |
+ previousMatchLength = 0; |
+ |
+ if (prevLine) { |
+ if (prevLine._commentContinues) { |
+ if (!(token = findMultilineCommentEnd(code))) { |
+ token = createSpan(code, "webkit-javascript-comment"); |
+ line._commentContinues = true; |
+ } |
+ } else if (prevLine._singleQuoteStringContinues) { |
+ if (!(token = findMultilineSingleQuoteStringEnd(code))) { |
+ token = createSpan(code, "webkit-javascript-string"); |
+ line._singleQuoteStringContinues = true; |
+ } |
+ } else if (prevLine._doubleQuoteStringContinues) { |
+ if (!(token = findMultilineDoubleQuoteStringEnd(code))) { |
+ token = createSpan(code, "webkit-javascript-string"); |
+ line._doubleQuoteStringContinues = true; |
+ } |
+ } else if (prevLine._regexpContinues) { |
+ if (!(token = findMultilineRegExpEnd(code))) { |
+ token = createSpan(code, "webkit-javascript-regexp"); |
+ line._regexpContinues = true; |
+ } |
+ } |
+ if (token) { |
+ i += previousMatchLength ? previousMatchLength : code.length; |
+ tmp = i; |
+ line.appendChild(token); |
+ } |
+ } |
+ |
+ for ( ; i < code.length; ++i) { |
+ var codeFragment = code.substr(i); |
+ var prevChar = code[i - 1]; |
+ token = findSingleLineComment(codeFragment); |
+ if (!token) { |
+ if ((token = findMultilineCommentStart(codeFragment))) |
+ line._commentContinues = true; |
+ else if (!prevChar || /^\W/.test(prevChar)) { |
+ token = findNumber(codeFragment, code[i - 1]) || |
+ findKeyword(codeFragment, code[i - 1]) || |
+ findSingleLineString(codeFragment) || |
+ findSingleLineRegExp(codeFragment); |
+ if (!token) { |
+ if (token = findMultilineSingleQuoteStringStart(codeFragment)) |
+ line._singleQuoteStringContinues = true; |
+ else if (token = findMultilineDoubleQuoteStringStart(codeFragment)) |
+ line._doubleQuoteStringContinues = true; |
+ else if (token = findMultilineRegExpStart(codeFragment)) |
+ line._regexpContinues = true; |
+ } |
+ } |
+ } |
+ |
+ if (token) { |
+ if (tmp !== i) |
+ line.appendChild(document.createTextNode(code.substring(tmp, i))); |
+ line.appendChild(token); |
+ i += previousMatchLength - 1; |
+ tmp = i + 1; |
+ } |
+ } |
+ |
+ if (tmp < code.length) |
+ line.appendChild(document.createTextNode(code.substring(tmp, i))); |
+ |
+ if (messageBubble) |
+ line.appendChild(messageBubble); |
+ } |
+ |
+ var i = 0; |
+ var rows = table.rows; |
+ var rowsLength = rows.length; |
+ var previousCell = null; |
+ var previousMatchLength = 0; |
+ var sourceFrame = this; |
+ |
+ // Split up the work into chunks so we don't block the |
+ // UI thread while processing. |
+ |
+ function processChunk() |
+ { |
+ for (var end = Math.min(i + 10, rowsLength); i < end; ++i) { |
+ var row = rows[i]; |
+ if (!row) |
+ continue; |
+ var cell = row.cells[1]; |
+ if (!cell) |
+ continue; |
+ syntaxHighlightJavascriptLine(cell, previousCell); |
+ if (i < (end - 1)) |
+ deleteContinueFlags(previousCell); |
+ previousCell = cell; |
+ } |
+ |
+ if (i >= rowsLength && processChunkInterval) { |
+ deleteContinueFlags(previousCell); |
+ clearInterval(processChunkInterval); |
+ |
+ sourceFrame.dispatchEventToListeners("syntax highlighting complete"); |
+ } |
+ } |
+ |
+ processChunk(); |
+ |
+ var processChunkInterval = setInterval(processChunk, 25); |
+ } |
+} |
+ |
+WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype; |
+ |