Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: resources/inspector/SourceFrame.js

Issue 853002: Updating the Chromium reference build for Windows. The continuous... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/reference_builds/chrome/
Patch Set: Added the symbol files back. Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « resources/inspector/SidebarTreeElement.js ('k') | resources/inspector/SourceView.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2009 Joseph Pecoraro
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 WebInspector.SourceFrame = function(element, addBreakpointDelegate)
28 {
29 this.messages = [];
30 this.breakpoints = [];
31 this._shortcuts = {};
32
33 this.addBreakpointDelegate = addBreakpointDelegate;
34
35 this.element = element || document.createElement("iframe");
36 this.element.addStyleClass("source-view-frame");
37 this.element.setAttribute("viewsource", "true");
38
39 this.element.addEventListener("load", this._loaded.bind(this), false);
40 }
41
42 WebInspector.SourceFrame.prototype = {
43 get executionLine()
44 {
45 return this._executionLine;
46 },
47
48 set executionLine(x)
49 {
50 if (this._executionLine === x)
51 return;
52
53 var previousLine = this._executionLine;
54 this._executionLine = x;
55
56 this._updateExecutionLine(previousLine);
57 },
58
59 get autoSizesToFitContentHeight()
60 {
61 return this._autoSizesToFitContentHeight;
62 },
63
64 set autoSizesToFitContentHeight(x)
65 {
66 if (this._autoSizesToFitContentHeight === x)
67 return;
68
69 this._autoSizesToFitContentHeight = x;
70
71 if (this._autoSizesToFitContentHeight) {
72 this._windowResizeListener = this._windowResized.bind(this);
73 window.addEventListener("resize", this._windowResizeListener, false) ;
74 this.sizeToFitContentHeight();
75 } else {
76 this.element.style.removeProperty("height");
77 if (this.element.contentDocument)
78 this.element.contentDocument.body.removeStyleClass("webkit-heigh t-sized-to-fit");
79 window.removeEventListener("resize", this._windowResizeListener, fal se);
80 delete this._windowResizeListener;
81 }
82 },
83
84 sourceRow: function(lineNumber)
85 {
86 if (!lineNumber || !this.element.contentDocument)
87 return;
88
89 var table = this.element.contentDocument.getElementsByTagName("table")[0 ];
90 if (!table)
91 return;
92
93 var rows = table.rows;
94
95 // Line numbers are a 1-based index, but the rows collection is 0-based.
96 --lineNumber;
97
98 return rows[lineNumber];
99 },
100
101 lineNumberForSourceRow: function(sourceRow)
102 {
103 // Line numbers are a 1-based index, but the rows collection is 0-based.
104 var lineNumber = 0;
105 while (sourceRow) {
106 ++lineNumber;
107 sourceRow = sourceRow.previousSibling;
108 }
109
110 return lineNumber;
111 },
112
113 revealLine: function(lineNumber)
114 {
115 if (!this._isContentLoaded()) {
116 this._lineNumberToReveal = lineNumber;
117 return;
118 }
119
120 var row = this.sourceRow(lineNumber);
121 if (row)
122 row.scrollIntoViewIfNeeded(true);
123 },
124
125 addBreakpoint: function(breakpoint)
126 {
127 this.breakpoints.push(breakpoint);
128 breakpoint.addEventListener("enabled", this._breakpointEnableChanged, th is);
129 breakpoint.addEventListener("disabled", this._breakpointEnableChanged, t his);
130 this._addBreakpointToSource(breakpoint);
131 },
132
133 removeBreakpoint: function(breakpoint)
134 {
135 this.breakpoints.remove(breakpoint);
136 breakpoint.removeEventListener("enabled", null, this);
137 breakpoint.removeEventListener("disabled", null, this);
138 this._removeBreakpointFromSource(breakpoint);
139 },
140
141 addMessage: function(msg)
142 {
143 // Don't add the message if there is no message or valid line or if the msg isn't an error or warning.
144 if (!msg.message || msg.line <= 0 || !msg.isErrorOrWarning())
145 return;
146 this.messages.push(msg);
147 this._addMessageToSource(msg);
148 },
149
150 clearMessages: function()
151 {
152 this.messages = [];
153
154 if (!this.element.contentDocument)
155 return;
156
157 var bubbles = this.element.contentDocument.querySelectorAll(".webkit-htm l-message-bubble");
158 if (!bubbles)
159 return;
160
161 for (var i = 0; i < bubbles.length; ++i) {
162 var bubble = bubbles[i];
163 bubble.parentNode.removeChild(bubble);
164 }
165 },
166
167 sizeToFitContentHeight: function()
168 {
169 if (this.element.contentDocument) {
170 this.element.style.setProperty("height", this.element.contentDocumen t.body.offsetHeight + "px");
171 this.element.contentDocument.body.addStyleClass("webkit-height-sized -to-fit");
172 }
173 },
174
175 _highlightLineEnds: function(event)
176 {
177 event.target.parentNode.removeStyleClass("webkit-highlighted-line");
178 },
179
180 highlightLine: function(lineNumber)
181 {
182 if (!this._isContentLoaded()) {
183 this._lineNumberToHighlight = lineNumber;
184 return;
185 }
186
187 var sourceRow = this.sourceRow(lineNumber);
188 if (!sourceRow)
189 return;
190 var line = sourceRow.getElementsByClassName('webkit-line-content')[0];
191 // Trick to reset the animation if the user clicks on the same link
192 // Using a timeout to avoid coalesced style updates
193 line.style.setProperty("-webkit-animation-name", "none");
194 setTimeout(function () {
195 line.style.removeProperty("-webkit-animation-name");
196 sourceRow.addStyleClass("webkit-highlighted-line");
197 }, 0);
198 },
199
200 _loaded: function()
201 {
202 WebInspector.addMainEventListeners(this.element.contentDocument);
203 this.element.contentDocument.addEventListener("contextmenu", this._docum entContextMenu.bind(this), true);
204 this.element.contentDocument.addEventListener("mousedown", this._documen tMouseDown.bind(this), true);
205 this.element.contentDocument.addEventListener("keydown", this._documentK eyDown.bind(this), true);
206 this.element.contentDocument.addEventListener("keyup", WebInspector.docu mentKeyUp.bind(WebInspector), true);
207 this.element.contentDocument.addEventListener("webkitAnimationEnd", this ._highlightLineEnds.bind(this), false);
208
209 // Register 'eval' shortcut.
210 var isMac = InspectorController.platform().indexOf("mac-") === 0;
211 var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Mod ifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl;
212 var shortcut = WebInspector.KeyboardShortcut.makeKey(69 /* 'E' */, platf ormSpecificModifier | WebInspector.KeyboardShortcut.Modifiers.Shift);
213 this._shortcuts[shortcut] = this._evalSelectionInCallFrame.bind(this);
214
215 var headElement = this.element.contentDocument.getElementsByTagName("hea d")[0];
216 if (!headElement) {
217 headElement = this.element.contentDocument.createElement("head");
218 this.element.contentDocument.documentElement.insertBefore(headElemen t, this.element.contentDocument.documentElement.firstChild);
219 }
220
221 var linkElement = this.element.contentDocument.createElement("link");
222 linkElement.type = "text/css";
223 linkElement.rel = "stylesheet";
224 linkElement.href = "inspectorSyntaxHighlight.css";
225 headElement.appendChild(linkElement);
226
227 var styleElement = this.element.contentDocument.createElement("style");
228 headElement.appendChild(styleElement);
229
230 // Add these style rules here since they are specific to the Inspector. They also behave oddly and not
231 // all properties apply if added to view-source.css (because it is a use r agent sheet.)
232 var styleText = ".webkit-line-number { background-repeat: no-repeat; bac kground-position: right 1px; }\n";
233 styleText += ".webkit-execution-line .webkit-line-number { color: transp arent; background-image: -webkit-canvas(program-counter); }\n";
234
235 styleText += ".webkit-breakpoint .webkit-line-number { color: white; bac kground-image: -webkit-canvas(breakpoint); }\n";
236 styleText += ".webkit-breakpoint-disabled .webkit-line-number { color: w hite; background-image: -webkit-canvas(breakpoint-disabled); }\n";
237 styleText += ".webkit-breakpoint.webkit-execution-line .webkit-line-numb er { color: transparent; background-image: -webkit-canvas(breakpoint-program-cou nter); }\n";
238 styleText += ".webkit-breakpoint-disabled.webkit-execution-line .webkit- line-number { color: transparent; background-image: -webkit-canvas(breakpoint-di sabled-program-counter); }\n";
239
240 styleText += ".webkit-breakpoint.webkit-breakpoint-conditional .webkit-l ine-number { color: white; background-image: -webkit-canvas(breakpoint-condition al); }\n";
241 styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint- disabled-conditional); }\n";
242 styleText += ".webkit-breakpoint.webkit-breakpoint-conditional.webkit-ex ecution-line .webkit-line-number { color: transparent; background-image: -webkit -canvas(breakpoint-conditional-program-counter); }\n";
243 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";
244
245 styleText += ".webkit-execution-line .webkit-line-content { background-c olor: rgb(171, 191, 254); outline: 1px solid rgb(64, 115, 244); }\n";
246 styleText += ".webkit-height-sized-to-fit { overflow-y: hidden }\n";
247 styleText += ".webkit-line-content { background-color: white; }\n";
248 styleText += "@-webkit-keyframes fadeout {from {background-color: rgb(25 5, 255, 120);} to { background-color: white;}}\n";
249 styleText += ".webkit-highlighted-line .webkit-line-content { background -color: rgb(255, 255, 120); -webkit-animation: 'fadeout' 2s 500ms}\n";
250
251 // TODO: Move these styles into inspector.css once https://bugs.webkit.o rg/show_bug.cgi?id=28913 is fixed and popup moved into the top frame.
252 styleText += ".popup-content { position: absolute; z-index: 10000; paddi ng: 4px; background-color: rgb(203, 226, 255); -webkit-border-radius: 7px; borde r: 2px solid rgb(169, 172, 203); }";
253 styleText += ".popup-glasspane { position: absolute; top: 0; left: 0; he ight: 100%; width: 100%; opacity: 0; z-index: 9900; }";
254 styleText += ".popup-message { background-color: transparent; font-famil y: 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 2p x 0; }";
255 styleText += ".popup-content.breakpoint-condition { width: 90%; }";
256 styleText += ".popup-content input#bp-condition { font-family: monospace ; margin: 0; border: 1px inset rgb(190, 190, 190) !important; width: 100%; box-s hadow: none !important; outline: none !important; -webkit-user-modify: read-writ e; }";
257 // This class is already in inspector.css
258 styleText += ".hidden { display: none !important; }";
259
260 styleElement.textContent = styleText;
261
262 this._needsProgramCounterImage = true;
263 this._needsBreakpointImages = true;
264
265 this.element.contentWindow.Element.prototype.addStyleClass = Element.pro totype.addStyleClass;
266 this.element.contentWindow.Element.prototype.removeStyleClass = Element. prototype.removeStyleClass;
267 this.element.contentWindow.Element.prototype.positionAt = Element.protot ype.positionAt;
268 this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses;
269 this.element.contentWindow.Element.prototype.hasStyleClass = Element.pro totype.hasStyleClass;
270 this.element.contentWindow.Element.prototype.pageOffsetRelativeToWindow = Element.prototype.pageOffsetRelativeToWindow;
271 this.element.contentWindow.Element.prototype.__defineGetter__("totalOffs etLeft", Element.prototype.__lookupGetter__("totalOffsetLeft"));
272 this.element.contentWindow.Element.prototype.__defineGetter__("totalOffs etTop", Element.prototype.__lookupGetter__("totalOffsetTop"));
273 this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNam e = Node.prototype.enclosingNodeOrSelfWithNodeName;
274 this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNam eInArray = Node.prototype.enclosingNodeOrSelfWithNodeNameInArray;
275
276 this._addExistingMessagesToSource();
277 this._addExistingBreakpointsToSource();
278 this._updateExecutionLine();
279 if (this._executionLine)
280 this.revealLine(this._executionLine);
281
282 if (this.autoSizesToFitContentHeight)
283 this.sizeToFitContentHeight();
284
285 if (this._lineNumberToReveal) {
286 this.revealLine(this._lineNumberToReveal);
287 delete this._lineNumberToReveal;
288 }
289
290 if (this._lineNumberToHighlight) {
291 this.highlightLine(this._lineNumberToHighlight);
292 delete this._lineNumberToHighlight;
293 }
294
295 this.dispatchEventToListeners("content loaded");
296 },
297
298 _isContentLoaded: function() {
299 var doc = this.element.contentDocument;
300 return doc && doc.getElementsByTagName("table")[0];
301 },
302
303 _windowResized: function(event)
304 {
305 if (!this._autoSizesToFitContentHeight)
306 return;
307 this.sizeToFitContentHeight();
308 },
309
310 _documentContextMenu: function(event)
311 {
312 if (!event.target.hasStyleClass("webkit-line-number"))
313 return;
314 var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
315 if (!sourceRow._breakpointObject && this.addBreakpointDelegate)
316 this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
317
318 var breakpoint = sourceRow._breakpointObject;
319 if (!breakpoint)
320 return;
321
322 this._editBreakpointCondition(event.target, sourceRow, breakpoint);
323 event.preventDefault();
324 },
325
326 _documentMouseDown: function(event)
327 {
328 if (!event.target.hasStyleClass("webkit-line-number"))
329 return;
330 if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
331 return;
332 var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
333 if (sourceRow._breakpointObject && sourceRow._breakpointObject.enabled)
334 sourceRow._breakpointObject.enabled = false;
335 else if (sourceRow._breakpointObject)
336 WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointOb ject);
337 else if (this.addBreakpointDelegate)
338 this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
339 },
340
341 _editBreakpointCondition: function(eventTarget, sourceRow, breakpoint)
342 {
343 // 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=289 13 is fixed.
344 var popupDocument = this.element.contentDocument;
345 this._showBreakpointConditionPopup(eventTarget, breakpoint.line, popupDo cument);
346
347 function committed(element, newText)
348 {
349 breakpoint.condition = newText;
350 if (breakpoint.condition)
351 sourceRow.addStyleClass("webkit-breakpoint-conditional");
352 else
353 sourceRow.removeStyleClass("webkit-breakpoint-conditional");
354 dismissed.call(this);
355 }
356
357 function dismissed()
358 {
359 this._popup.hide();
360 delete this._conditionEditorElement;
361 }
362
363 var dismissedHandler = dismissed.bind(this);
364 this._conditionEditorElement.addEventListener("blur", dismissedHandler, false);
365
366 WebInspector.startEditing(this._conditionEditorElement, committed.bind(t his), dismissedHandler);
367 this._conditionEditorElement.value = breakpoint.condition;
368 this._conditionEditorElement.select();
369 },
370
371 _showBreakpointConditionPopup: function(clickedElement, lineNumber, popupDoc ument)
372 {
373 var popupContentElement = this._createPopupElement(lineNumber, popupDocu ment);
374 var lineElement = clickedElement.enclosingNodeOrSelfWithNodeName("td").n extSibling;
375 if (this._popup) {
376 this._popup.hide();
377 this._popup.element = popupContentElement;
378 } else {
379 this._popup = new WebInspector.Popup(popupContentElement);
380 this._popup.autoHide = true;
381 }
382 this._popup.anchor = lineElement;
383 this._popup.show();
384 },
385
386 _createPopupElement: function(lineNumber, popupDocument)
387 {
388 var popupContentElement = popupDocument.createElement("div");
389 popupContentElement.className = "popup-content breakpoint-condition";
390
391 var labelElement = document.createElement("label");
392 labelElement.className = "popup-message";
393 labelElement.htmlFor = "bp-condition";
394 labelElement.appendChild(document.createTextNode(WebInspector.UIString(" The breakpoint on line %d will stop only if this expression is true:", lineNumbe r)));
395 popupContentElement.appendChild(labelElement);
396
397 var editorElement = document.createElement("input");
398 editorElement.id = "bp-condition";
399 editorElement.type = "text"
400 popupContentElement.appendChild(editorElement);
401 this._conditionEditorElement = editorElement;
402
403 return popupContentElement;
404 },
405
406 _documentKeyDown: function(event)
407 {
408 var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
409 var handler = this._shortcuts[shortcut];
410 if (handler) {
411 handler(event);
412 event.preventDefault();
413 } else {
414 WebInspector.documentKeyDown(event);
415 }
416 },
417
418 _evalSelectionInCallFrame: function(event)
419 {
420 if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
421 return;
422
423 var selection = this.element.contentWindow.getSelection();
424 if (!selection.rangeCount)
425 return;
426
427 var expression = selection.getRangeAt(0).toString().trimWhitespace();
428 WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, fals e, function(result, exception) {
429 WebInspector.showConsole();
430 var commandMessage = new WebInspector.ConsoleCommand(expression);
431 WebInspector.console.addMessage(commandMessage);
432 WebInspector.console.addMessage(new WebInspector.ConsoleCommandResul t(result, exception, commandMessage));
433 });
434 },
435
436 _breakpointEnableChanged: function(event)
437 {
438 var breakpoint = event.target;
439 var sourceRow = this.sourceRow(breakpoint.line);
440 if (!sourceRow)
441 return;
442
443 sourceRow.addStyleClass("webkit-breakpoint");
444
445 if (breakpoint.enabled)
446 sourceRow.removeStyleClass("webkit-breakpoint-disabled");
447 else
448 sourceRow.addStyleClass("webkit-breakpoint-disabled");
449 },
450
451 _updateExecutionLine: function(previousLine)
452 {
453 if (previousLine) {
454 var sourceRow = this.sourceRow(previousLine);
455 if (sourceRow)
456 sourceRow.removeStyleClass("webkit-execution-line");
457 }
458
459 if (!this._executionLine)
460 return;
461
462 this._drawProgramCounterImageIfNeeded();
463
464 var sourceRow = this.sourceRow(this._executionLine);
465 if (sourceRow)
466 sourceRow.addStyleClass("webkit-execution-line");
467 },
468
469 _addExistingBreakpointsToSource: function()
470 {
471 var length = this.breakpoints.length;
472 for (var i = 0; i < length; ++i)
473 this._addBreakpointToSource(this.breakpoints[i]);
474 },
475
476 _addBreakpointToSource: function(breakpoint)
477 {
478 var sourceRow = this.sourceRow(breakpoint.line);
479 if (!sourceRow)
480 return;
481
482 breakpoint.sourceText = sourceRow.getElementsByClassName('webkit-line-co ntent')[0].textContent;
483
484 this._drawBreakpointImagesIfNeeded();
485
486 sourceRow._breakpointObject = breakpoint;
487
488 sourceRow.addStyleClass("webkit-breakpoint");
489 if (!breakpoint.enabled)
490 sourceRow.addStyleClass("webkit-breakpoint-disabled");
491 if (breakpoint.condition)
492 sourceRow.addStyleClass("webkit-breakpoint-conditional");
493 },
494
495 _removeBreakpointFromSource: function(breakpoint)
496 {
497 var sourceRow = this.sourceRow(breakpoint.line);
498 if (!sourceRow)
499 return;
500
501 delete sourceRow._breakpointObject;
502
503 sourceRow.removeStyleClass("webkit-breakpoint");
504 sourceRow.removeStyleClass("webkit-breakpoint-disabled");
505 sourceRow.removeStyleClass("webkit-breakpoint-conditional");
506 },
507
508 _incrementMessageRepeatCount: function(msg, repeatDelta)
509 {
510 if (!msg._resourceMessageLineElement)
511 return;
512
513 if (!msg._resourceMessageRepeatCountElement) {
514 var repeatedElement = document.createElement("span");
515 msg._resourceMessageLineElement.appendChild(repeatedElement);
516 msg._resourceMessageRepeatCountElement = repeatedElement;
517 }
518
519 msg.repeatCount += repeatDelta;
520 msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIStri ng(" (repeated %d times)", msg.repeatCount);
521 },
522
523 _addExistingMessagesToSource: function()
524 {
525 var length = this.messages.length;
526 for (var i = 0; i < length; ++i)
527 this._addMessageToSource(this.messages[i]);
528 },
529
530 _addMessageToSource: function(msg)
531 {
532 var row = this.sourceRow(msg.line);
533 if (!row)
534 return;
535
536 var cell = row.cells[1];
537 if (!cell)
538 return;
539
540 var messageBubbleElement = cell.lastChild;
541 if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEM ENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) {
542 messageBubbleElement = this.element.contentDocument.createElement("d iv");
543 messageBubbleElement.className = "webkit-html-message-bubble";
544 cell.appendChild(messageBubbleElement);
545 }
546
547 if (!row.messages)
548 row.messages = [];
549
550 for (var i = 0; i < row.messages.length; ++i) {
551 if (row.messages[i].isEqual(msg, true)) {
552 this._incrementMessageRepeatCount(row.messages[i], msg.repeatDel ta);
553 return;
554 }
555 }
556
557 row.messages.push(msg);
558
559 var imageURL;
560 switch (msg.level) {
561 case WebInspector.ConsoleMessage.MessageLevel.Error:
562 messageBubbleElement.addStyleClass("webkit-html-error-message");
563 imageURL = "Images/errorIcon.png";
564 break;
565 case WebInspector.ConsoleMessage.MessageLevel.Warning:
566 messageBubbleElement.addStyleClass("webkit-html-warning-message" );
567 imageURL = "Images/warningIcon.png";
568 break;
569 }
570
571 var messageLineElement = this.element.contentDocument.createElement("div ");
572 messageLineElement.className = "webkit-html-message-line";
573 messageBubbleElement.appendChild(messageLineElement);
574
575 // Create the image element in the Inspector's document so we can use re lative image URLs.
576 var image = document.createElement("img");
577 image.src = imageURL;
578 image.className = "webkit-html-message-icon";
579
580 // Adopt the image element since it wasn't created in element's contentD ocument.
581 image = this.element.contentDocument.adoptNode(image);
582 messageLineElement.appendChild(image);
583 messageLineElement.appendChild(this.element.contentDocument.createTextNo de(msg.message));
584
585 msg._resourceMessageLineElement = messageLineElement;
586 },
587
588 _drawProgramCounterInContext: function(ctx, glow)
589 {
590 if (glow)
591 ctx.save();
592
593 ctx.beginPath();
594 ctx.moveTo(17, 2);
595 ctx.lineTo(19, 2);
596 ctx.lineTo(19, 0);
597 ctx.lineTo(21, 0);
598 ctx.lineTo(26, 5.5);
599 ctx.lineTo(21, 11);
600 ctx.lineTo(19, 11);
601 ctx.lineTo(19, 9);
602 ctx.lineTo(17, 9);
603 ctx.closePath();
604 ctx.fillStyle = "rgb(142, 5, 4)";
605
606 if (glow) {
607 ctx.shadowBlur = 4;
608 ctx.shadowColor = "rgb(255, 255, 255)";
609 ctx.shadowOffsetX = -1;
610 ctx.shadowOffsetY = 0;
611 }
612
613 ctx.fill();
614 ctx.fill(); // Fill twice to get a good shadow and darker anti-aliased p ixels.
615
616 if (glow)
617 ctx.restore();
618 },
619
620 _drawProgramCounterImageIfNeeded: function()
621 {
622 if (!this._needsProgramCounterImage || !this.element.contentDocument)
623 return;
624
625 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "progra m-counter", 26, 11);
626 ctx.clearRect(0, 0, 26, 11);
627 this._drawProgramCounterInContext(ctx, true);
628
629 delete this._needsProgramCounterImage;
630 },
631
632 _drawBreakpointImagesIfNeeded: function(conditional)
633 {
634 if (!this._needsBreakpointImages || !this.element.contentDocument)
635 return;
636
637 function drawBreakpoint(ctx, disabled, conditional)
638 {
639 ctx.beginPath();
640 ctx.moveTo(0, 2);
641 ctx.lineTo(2, 0);
642 ctx.lineTo(21, 0);
643 ctx.lineTo(26, 5.5);
644 ctx.lineTo(21, 11);
645 ctx.lineTo(2, 11);
646 ctx.lineTo(0, 9);
647 ctx.closePath();
648 ctx.fillStyle = conditional ? "rgb(217, 142, 1)" : "rgb(1, 142, 217) ";
649 ctx.strokeStyle = conditional ? "rgb(205, 103, 0)" : "rgb(0, 103, 20 5)";
650 ctx.lineWidth = 3;
651 ctx.fill();
652 ctx.save();
653 ctx.clip();
654 ctx.stroke();
655 ctx.restore();
656
657 if (!disabled)
658 return;
659
660 ctx.save();
661 ctx.globalCompositeOperation = "destination-out";
662 ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
663 ctx.fillRect(0, 0, 26, 11);
664 ctx.restore();
665 }
666
667
668 // Unconditional breakpoints.
669
670 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint", 26, 11);
671 ctx.clearRect(0, 0, 26, 11);
672 drawBreakpoint(ctx);
673
674 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-program-counter", 26, 11);
675 ctx.clearRect(0, 0, 26, 11);
676 drawBreakpoint(ctx);
677 ctx.clearRect(20, 0, 6, 11);
678 this._drawProgramCounterInContext(ctx, true);
679
680 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-disabled", 26, 11);
681 ctx.clearRect(0, 0, 26, 11);
682 drawBreakpoint(ctx, true);
683
684 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-disabled-program-counter", 26, 11);
685 ctx.clearRect(0, 0, 26, 11);
686 drawBreakpoint(ctx, true);
687 ctx.clearRect(20, 0, 6, 11);
688 this._drawProgramCounterInContext(ctx, true);
689
690
691 // Conditional breakpoints.
692
693 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-conditional", 26, 11);
694 ctx.clearRect(0, 0, 26, 11);
695 drawBreakpoint(ctx, false, true);
696
697 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-conditional-program-counter", 26, 11);
698 ctx.clearRect(0, 0, 26, 11);
699 drawBreakpoint(ctx, false, true);
700 ctx.clearRect(20, 0, 6, 11);
701 this._drawProgramCounterInContext(ctx, true);
702
703 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-disabled-conditional", 26, 11);
704 ctx.clearRect(0, 0, 26, 11);
705 drawBreakpoint(ctx, true, true);
706
707 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-disabled-conditional-program-counter", 26, 11);
708 ctx.clearRect(0, 0, 26, 11);
709 drawBreakpoint(ctx, true, true);
710 ctx.clearRect(20, 0, 6, 11);
711 this._drawProgramCounterInContext(ctx, true);
712
713 delete this._needsBreakpointImages;
714 },
715
716 syntaxHighlightJavascript: function()
717 {
718 var table = this.element.contentDocument.getElementsByTagName("table")[0 ];
719 if (!table)
720 return;
721
722 var jsSyntaxHighlighter = new WebInspector.JavaScriptSourceSyntaxHighlig hter(table, this);
723 jsSyntaxHighlighter.process();
724 },
725
726 syntaxHighlightCSS: function()
727 {
728 var table = this.element.contentDocument.getElementsByTagName("table")[0 ];
729 if (!table)
730 return;
731
732 var cssSyntaxHighlighter = new WebInspector.CSSSourceSyntaxHighligher(ta ble, this);
733 cssSyntaxHighlighter.process();
734 }
735 }
736
737 WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype;
738
739 WebInspector.SourceSyntaxHighligher = function(table, sourceFrame)
740 {
741 this.table = table;
742 this.sourceFrame = sourceFrame;
743 }
744
745 WebInspector.SourceSyntaxHighligher.prototype = {
746 createSpan: function(content, className)
747 {
748 var span = document.createElement("span");
749 span.className = className;
750 span.appendChild(document.createTextNode(content));
751 return span;
752 },
753
754 generateFinder: function(regex, matchNumber, className)
755 {
756 return function(str) {
757 var match = regex.exec(str);
758 if (!match)
759 return null;
760 this.previousMatchLength = match[matchNumber].length;
761 return this.createSpan(match[matchNumber], className);
762 };
763 },
764
765 process: function()
766 {
767 // Split up the work into chunks so we don't block the
768 // UI thread while processing.
769
770 var i = 0;
771 var rows = this.table.rows;
772 var rowsLength = rows.length;
773 var previousCell = null;
774 const linesPerChunk = 10;
775
776 function processChunk()
777 {
778 for (var end = Math.min(i + linesPerChunk, rowsLength); i < end; ++i ) {
779 var row = rows[i];
780 if (!row)
781 continue;
782 var cell = row.cells[1];
783 if (!cell)
784 continue;
785 this.syntaxHighlightLine(cell, previousCell);
786 if (i < (end - 1))
787 this.deleteContinueFlags(previousCell);
788 previousCell = cell;
789 }
790
791 if (i >= rowsLength && processChunkInterval) {
792 this.deleteContinueFlags(previousCell);
793 delete this.previousMatchLength;
794 clearInterval(processChunkInterval);
795
796 this.sourceFrame.dispatchEventToListeners("syntax highlighting c omplete");
797 }
798 }
799
800 var boundProcessChunk = processChunk.bind(this);
801 var processChunkInterval = setInterval(boundProcessChunk, 25);
802 boundProcessChunk();
803 }
804 }
805
806 WebInspector.CSSSourceSyntaxHighligher = function(table, sourceFrame) {
807 WebInspector.SourceSyntaxHighligher.call(this, table, sourceFrame);
808
809 this.findNumber = this.generateFinder(/^((-?(\d+|\d*\.\d+))|^(#[a-fA-F0-9]{3 ,6}))(?:\D|$)/, 1, "webkit-css-number");
810 this.findUnits = this.generateFinder(/^(px|em|pt|in|cm|mm|pc|ex)(?:\W|$)/, 1 , "webkit-css-unit");
811 this.findKeyword = this.generateFinder(/^(rgba?|hsla?|var)(?:\W|$)/, 1, "web kit-css-keyword");
812 this.findSingleLineString = this.generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\ ]|\\.)*'/, 0, "webkit-css-string"); // " this quote keeps Xcode happy
813 this.findSingleLineComment = this.generateFinder(/^\/\*.*?\*\//, 0, "webkit- css-comment");
814 this.findMultilineCommentStart = this.generateFinder(/^\/\*.*$/, 0, "webkit- css-comment");
815 this.findMultilineCommentEnd = this.generateFinder(/^.*?\*\//, 0, "webkit-cs s-comment");
816 this.findSelector = this.generateFinder(/^([#\.]?[_a-zA-Z].*?)(?:\W|$)/, 1, "webkit-css-selector");
817 this.findProperty = this.generateFinder(/^(-?[_a-z0-9][_a-z0-9-]*\s*)(?:\:)/ , 1, "webkit-css-property");
818 this.findGenericIdent = this.generateFinder(/^([@-]?[_a-z0-9][_a-z0-9-]*)(?: \W|$)/, 1, "webkit-css-string");
819 }
820
821 WebInspector.CSSSourceSyntaxHighligher.prototype = {
822 deleteContinueFlags: function(cell)
823 {
824 if (!cell)
825 return;
826 delete cell._commentContinues;
827 delete cell._inSelector;
828 },
829
830 findPseudoClass: function(str)
831 {
832 var match = /^(::?)([_a-z0-9][_a-z0-9-]*)/.exec(str);
833 if (!match)
834 return null;
835 this.previousMatchLength = match[0].length;
836 var span = document.createElement("span");
837 span.appendChild(document.createTextNode(match[1]));
838 span.appendChild(this.createSpan(match[2], "webkit-css-pseudo-class"));
839 return span;
840 },
841
842 findURL: function(str)
843 {
844 var match = /^(?:local|url)\(([^\)]*?)\)/.exec(str);
845 if (!match)
846 return null;
847 this.previousMatchLength = match[0].length;
848 var innerUrlSpan = this.createSpan(match[1], "webkit-css-url");
849 var outerSpan = document.createElement("span");
850 outerSpan.appendChild(this.createSpan("url", "webkit-css-keyword"));
851 outerSpan.appendChild(document.createTextNode("("));
852 outerSpan.appendChild(innerUrlSpan);
853 outerSpan.appendChild(document.createTextNode(")"));
854 return outerSpan;
855 },
856
857 findAtRule: function(str)
858 {
859 var match = /^@[_a-z0-9][_a-z0-9-]*(?:\W|$)/.exec(str);
860 if (!match)
861 return null;
862 this.previousMatchLength = match[0].length;
863 return this.createSpan(match[0], "webkit-css-at-rule");
864 },
865
866 syntaxHighlightLine: function(line, prevLine)
867 {
868 var code = line.textContent;
869 while (line.firstChild)
870 line.removeChild(line.firstChild);
871
872 var token;
873 var tmp = 0;
874 var i = 0;
875 this.previousMatchLength = 0;
876
877 if (prevLine) {
878 if (prevLine._commentContinues) {
879 if (!(token = this.findMultilineCommentEnd(code))) {
880 token = this.createSpan(code, "webkit-javascript-comment");
881 line._commentContinues = true;
882 }
883 }
884 if (token) {
885 i += this.previousMatchLength ? this.previousMatchLength : code. length;
886 tmp = i;
887 line.appendChild(token);
888 }
889 }
890
891 var inSelector = (prevLine && prevLine._inSelector); // inside a selecto r, we can now parse properties and values
892 var inAtRuleBlock = (prevLine && prevLine._inAtRuleBlock); // inside an @rule block, but not necessarily inside a selector yet
893 var atRuleStarted = (prevLine && prevLine._atRuleStarted); // we receive d an @rule, we may stop the @rule at a semicolon or open a block and become inAt RuleBlock
894 var atRuleIsSelector = (prevLine && prevLine._atRuleIsSelector); // when this @rule opens a block it immediately goes into parsing properties and values instead of selectors
895
896 for ( ; i < code.length; ++i) {
897 var codeFragment = code.substr(i);
898 var prevChar = code[i - 1];
899 var currChar = codeFragment[0];
900 token = this.findSingleLineComment(codeFragment);
901 if (!token) {
902 if ((token = this.findMultilineCommentStart(codeFragment)))
903 line._commentContinues = true;
904 else if (currChar === ";" && !inAtRuleBlock)
905 atRuleStarted = false;
906 else if (currChar === "}") {
907 if (inSelector && inAtRuleBlock && atRuleIsSelector) {
908 inSelector = false;
909 inAtRuleBlock = false;
910 atRuleStarted = false;
911 } else if (inSelector) {
912 inSelector = false;
913 } else if (inAtRuleBlock) {
914 inAtRuleBlock = false;
915 atRuleStarted = false;
916 }
917 } else if (currChar === "{") {
918 if (!atRuleStarted || inAtRuleBlock) {
919 inSelector = true;
920 } else if (!inAtRuleBlock && atRuleIsSelector) {
921 inAtRuleBlock = true;
922 inSelector = true;
923 } else if (!inAtRuleBlock) {
924 inAtRuleBlock = true;
925 inSelector = false;
926 }
927 } else if (inSelector) {
928 if (!prevChar || /^\d/.test(prevChar)) {
929 token = this.findUnits(codeFragment);
930 } else if (!prevChar || /^\W/.test(prevChar)) {
931 token = this.findNumber(codeFragment) ||
932 this.findKeyword(codeFragment) ||
933 this.findURL(codeFragment) ||
934 this.findProperty(codeFragment) ||
935 this.findAtRule(codeFragment) ||
936 this.findGenericIdent(codeFragment) ||
937 this.findSingleLineString(codeFragment);
938 }
939 } else if (!inSelector) {
940 if (atRuleStarted && !inAtRuleBlock)
941 token = this.findURL(codeFragment); // for @import
942 if (!token) {
943 token = this.findSelector(codeFragment) ||
944 this.findPseudoClass(codeFragment) ||
945 this.findAtRule(codeFragment);
946 }
947 }
948 }
949
950 if (token) {
951 if (currChar === "@") {
952 atRuleStarted = true;
953
954 // The @font-face, @page, and @variables at-rules do not con tain selectors like other at-rules
955 // instead it acts as a selector and contains properties and values.
956 var text = token.textContent;
957 atRuleIsSelector = /font-face/.test(text) || /page/.test(tex t) || /variables/.test(text);
958 }
959
960 if (tmp !== i)
961 line.appendChild(document.createTextNode(code.substring(tmp, i)));
962 line.appendChild(token);
963 i += this.previousMatchLength - 1;
964 tmp = i + 1;
965 }
966 }
967
968 line._inSelector = inSelector;
969 line._inAtRuleBlock = inAtRuleBlock;
970 line._atRuleStarted = atRuleStarted;
971 line._atRuleIsSelector = atRuleIsSelector;
972
973 if (tmp < code.length)
974 line.appendChild(document.createTextNode(code.substring(tmp, i)));
975 }
976 }
977
978 WebInspector.CSSSourceSyntaxHighligher.prototype.__proto__ = WebInspector.Source SyntaxHighligher.prototype;
979
980 WebInspector.JavaScriptSourceSyntaxHighlighter = function(table, sourceFrame) {
981 WebInspector.SourceSyntaxHighligher.call(this, table, sourceFrame);
982
983 this.findNumber = this.generateFinder(/^(-?(\d+\.?\d*([eE][+-]\d+)?|0[xX]\h+ |Infinity)|NaN)(?:\W|$)/, 1, "webkit-javascript-number");
984 this.findKeyword = this.generateFinder(/^(null|true|false|break|case|catch|c onst|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|expor t|extends|import|super|get|set)(?:\W|$)/, 1, "webkit-javascript-keyword");
985 this.findSingleLineString = this.generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\ ]|\\.)*'/, 0, "webkit-javascript-string"); // " this quote keeps Xcode happy
986 this.findMultilineCommentStart = this.generateFinder(/^\/\*.*$/, 0, "webkit- javascript-comment");
987 this.findMultilineCommentEnd = this.generateFinder(/^.*?\*\//, 0, "webkit-ja vascript-comment");
988 this.findMultilineSingleQuoteStringStart = this.generateFinder(/^'(?:[^'\\]| \\.)*\\$/, 0, "webkit-javascript-string");
989 this.findMultilineSingleQuoteStringEnd = this.generateFinder(/^(?:[^'\\]|\\. )*?'/, 0, "webkit-javascript-string");
990 this.findMultilineDoubleQuoteStringStart = this.generateFinder(/^"(?:[^"\\]| \\.)*\\$/, 0, "webkit-javascript-string");
991 this.findMultilineDoubleQuoteStringEnd = this.generateFinder(/^(?:[^"\\]|\\. )*?"/, 0, "webkit-javascript-string");
992 this.findMultilineRegExpEnd = this.generateFinder(/^(?:[^\/\\]|\\.)*?\/([gim ]{0,3})/, 0, "webkit-javascript-regexp");
993 this.findSingleLineComment = this.generateFinder(/^\/\/.*|^\/\*.*?\*\//, 0, "webkit-javascript-comment");
994 }
995
996 WebInspector.JavaScriptSourceSyntaxHighlighter.prototype = {
997 deleteContinueFlags: function(cell)
998 {
999 if (!cell)
1000 return;
1001 delete cell._commentContinues;
1002 delete cell._singleQuoteStringContinues;
1003 delete cell._doubleQuoteStringContinues;
1004 delete cell._regexpContinues;
1005 },
1006
1007 findMultilineRegExpStart: function(str)
1008 {
1009 var match = /^\/(?:[^\/\\]|\\.)*\\$/.exec(str);
1010 if (!match || !/\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[0]))
1011 return null;
1012 this.previousMatchLength = match[0].length;
1013 return this.createSpan(match[0], "webkit-javascript-regexp");
1014 },
1015
1016 findSingleLineRegExp: function(str)
1017 {
1018 var match = /^(\/(?:[^\/\\]|\\.)*\/([gim]{0,3}))(.?)/.exec(str);
1019 if (!match || !(match[2].length > 0 || /\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.t est(match[1]) || /\.|;|,/.test(match[3])))
1020 return null;
1021 this.previousMatchLength = match[1].length;
1022 return this.createSpan(match[1], "webkit-javascript-regexp");
1023 },
1024
1025 syntaxHighlightLine: function(line, prevLine)
1026 {
1027 var messageBubble = line.lastChild;
1028 if (messageBubble && messageBubble.nodeType === Node.ELEMENT_NODE && mes sageBubble.hasStyleClass("webkit-html-message-bubble"))
1029 line.removeChild(messageBubble);
1030 else
1031 messageBubble = null;
1032
1033 var code = line.textContent;
1034
1035 while (line.firstChild)
1036 line.removeChild(line.firstChild);
1037
1038 var token;
1039 var tmp = 0;
1040 var i = 0;
1041 this.previousMatchLength = 0;
1042
1043 if (prevLine) {
1044 if (prevLine._commentContinues) {
1045 if (!(token = this.findMultilineCommentEnd(code))) {
1046 token = this.createSpan(code, "webkit-javascript-comment");
1047 line._commentContinues = true;
1048 }
1049 } else if (prevLine._singleQuoteStringContinues) {
1050 if (!(token = this.findMultilineSingleQuoteStringEnd(code))) {
1051 token = this.createSpan(code, "webkit-javascript-string");
1052 line._singleQuoteStringContinues = true;
1053 }
1054 } else if (prevLine._doubleQuoteStringContinues) {
1055 if (!(token = this.findMultilineDoubleQuoteStringEnd(code))) {
1056 token = this.createSpan(code, "webkit-javascript-string");
1057 line._doubleQuoteStringContinues = true;
1058 }
1059 } else if (prevLine._regexpContinues) {
1060 if (!(token = this.findMultilineRegExpEnd(code))) {
1061 token = this.createSpan(code, "webkit-javascript-regexp");
1062 line._regexpContinues = true;
1063 }
1064 }
1065 if (token) {
1066 i += this.previousMatchLength ? this.previousMatchLength : code. length;
1067 tmp = i;
1068 line.appendChild(token);
1069 }
1070 }
1071
1072 for ( ; i < code.length; ++i) {
1073 var codeFragment = code.substr(i);
1074 var prevChar = code[i - 1];
1075 token = this.findSingleLineComment(codeFragment);
1076 if (!token) {
1077 if ((token = this.findMultilineCommentStart(codeFragment)))
1078 line._commentContinues = true;
1079 else if (!prevChar || /^\W/.test(prevChar)) {
1080 token = this.findNumber(codeFragment) ||
1081 this.findKeyword(codeFragment) ||
1082 this.findSingleLineString(codeFragment) ||
1083 this.findSingleLineRegExp(codeFragment);
1084 if (!token) {
1085 if (token = this.findMultilineSingleQuoteStringStart(cod eFragment))
1086 line._singleQuoteStringContinues = true;
1087 else if (token = this.findMultilineDoubleQuoteStringStar t(codeFragment))
1088 line._doubleQuoteStringContinues = true;
1089 else if (token = this.findMultilineRegExpStart(codeFragm ent))
1090 line._regexpContinues = true;
1091 }
1092 }
1093 }
1094
1095 if (token) {
1096 if (tmp !== i)
1097 line.appendChild(document.createTextNode(code.substring(tmp, i)));
1098 line.appendChild(token);
1099 i += this.previousMatchLength - 1;
1100 tmp = i + 1;
1101 }
1102 }
1103
1104 if (tmp < code.length)
1105 line.appendChild(document.createTextNode(code.substring(tmp, i)));
1106
1107 if (messageBubble)
1108 line.appendChild(messageBubble);
1109 }
1110 }
1111
1112 WebInspector.JavaScriptSourceSyntaxHighlighter.prototype.__proto__ = WebInspecto r.SourceSyntaxHighligher.prototype;
OLDNEW
« no previous file with comments | « resources/inspector/SidebarTreeElement.js ('k') | resources/inspector/SourceView.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698