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

Side by Side Diff: chrome_frame/tools/test/reference_build/chrome/resources/inspector/SourceFrame.js

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 2 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
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 WebInspector.SourceFrame = function(element, addBreakpointDelegate)
27 {
28 this.messages = [];
29 this.breakpoints = [];
30 this._shortcuts = {};
31
32 this.addBreakpointDelegate = addBreakpointDelegate;
33
34 this.element = element || document.createElement("iframe");
35 this.element.addStyleClass("source-view-frame");
36 this.element.setAttribute("viewsource", "true");
37
38 this.element.addEventListener("load", this._loaded.bind(this), false);
39 }
40
41 WebInspector.SourceFrame.prototype = {
42 get executionLine()
43 {
44 return this._executionLine;
45 },
46
47 set executionLine(x)
48 {
49 if (this._executionLine === x)
50 return;
51
52 var previousLine = this._executionLine;
53 this._executionLine = x;
54
55 this._updateExecutionLine(previousLine);
56 },
57
58 get autoSizesToFitContentHeight()
59 {
60 return this._autoSizesToFitContentHeight;
61 },
62
63 set autoSizesToFitContentHeight(x)
64 {
65 if (this._autoSizesToFitContentHeight === x)
66 return;
67
68 this._autoSizesToFitContentHeight = x;
69
70 if (this._autoSizesToFitContentHeight) {
71 this._windowResizeListener = this._windowResized.bind(this);
72 window.addEventListener("resize", this._windowResizeListener, false) ;
73 this.sizeToFitContentHeight();
74 } else {
75 this.element.style.removeProperty("height");
76 if (this.element.contentDocument)
77 this.element.contentDocument.body.removeStyleClass("webkit-heigh t-sized-to-fit");
78 window.removeEventListener("resize", this._windowResizeListener, fal se);
79 delete this._windowResizeListener;
80 }
81 },
82
83 sourceRow: function(lineNumber)
84 {
85 if (!lineNumber || !this.element.contentDocument)
86 return;
87
88 var table = this.element.contentDocument.getElementsByTagName("table")[0 ];
89 if (!table)
90 return;
91
92 var rows = table.rows;
93
94 // Line numbers are a 1-based index, but the rows collection is 0-based.
95 --lineNumber;
96
97 return rows[lineNumber];
98 },
99
100 lineNumberForSourceRow: function(sourceRow)
101 {
102 // Line numbers are a 1-based index, but the rows collection is 0-based.
103 var lineNumber = 0;
104 while (sourceRow) {
105 ++lineNumber;
106 sourceRow = sourceRow.previousSibling;
107 }
108
109 return lineNumber;
110 },
111
112 revealLine: function(lineNumber)
113 {
114 if (!this._isContentLoaded()) {
115 this._lineNumberToReveal = lineNumber;
116 return;
117 }
118
119 var row = this.sourceRow(lineNumber);
120 if (row)
121 row.scrollIntoViewIfNeeded(true);
122 },
123
124 addBreakpoint: function(breakpoint)
125 {
126 this.breakpoints.push(breakpoint);
127 breakpoint.addEventListener("enabled", this._breakpointEnableChanged, th is);
128 breakpoint.addEventListener("disabled", this._breakpointEnableChanged, t his);
129 this._addBreakpointToSource(breakpoint);
130 },
131
132 removeBreakpoint: function(breakpoint)
133 {
134 this.breakpoints.remove(breakpoint);
135 breakpoint.removeEventListener("enabled", null, this);
136 breakpoint.removeEventListener("disabled", null, this);
137 this._removeBreakpointFromSource(breakpoint);
138 },
139
140 addMessage: function(msg)
141 {
142 // Don't add the message if there is no message or valid line or if the msg isn't an error or warning.
143 if (!msg.message || msg.line <= 0 || !msg.isErrorOrWarning())
144 return;
145 this.messages.push(msg);
146 this._addMessageToSource(msg);
147 },
148
149 clearMessages: function()
150 {
151 this.messages = [];
152
153 if (!this.element.contentDocument)
154 return;
155
156 var bubbles = this.element.contentDocument.querySelectorAll(".webkit-htm l-message-bubble");
157 if (!bubbles)
158 return;
159
160 for (var i = 0; i < bubbles.length; ++i) {
161 var bubble = bubbles[i];
162 bubble.parentNode.removeChild(bubble);
163 }
164 },
165
166 sizeToFitContentHeight: function()
167 {
168 if (this.element.contentDocument) {
169 this.element.style.setProperty("height", this.element.contentDocumen t.body.offsetHeight + "px");
170 this.element.contentDocument.body.addStyleClass("webkit-height-sized -to-fit");
171 }
172 },
173
174 _highlightLineEnds: function(event)
175 {
176 event.target.parentNode.removeStyleClass("webkit-highlighted-line");
177 },
178
179 highlightLine: function(lineNumber)
180 {
181 if (!this._isContentLoaded()) {
182 this._lineNumberToHighlight = lineNumber;
183 return;
184 }
185
186 var sourceRow = this.sourceRow(lineNumber);
187 if (!sourceRow)
188 return;
189 var line = sourceRow.getElementsByClassName('webkit-line-content')[0];
190 // Trick to reset the animation if the user clicks on the same link
191 // Using a timeout to avoid coalesced style updates
192 line.style.setProperty("-webkit-animation-name", "none");
193 setTimeout(function () {
194 line.style.removeProperty("-webkit-animation-name");
195 sourceRow.addStyleClass("webkit-highlighted-line");
196 }, 0);
197 },
198
199 _loaded: function()
200 {
201 WebInspector.addMainEventListeners(this.element.contentDocument);
202 this.element.contentDocument.addEventListener("contextmenu", this._docum entContextMenu.bind(this), true);
203 this.element.contentDocument.addEventListener("mousedown", this._documen tMouseDown.bind(this), true);
204 this.element.contentDocument.addEventListener("keydown", this._documentK eyDown.bind(this), true);
205 this.element.contentDocument.addEventListener("keyup", WebInspector.docu mentKeyUp.bind(WebInspector), true);
206 this.element.contentDocument.addEventListener("webkitAnimationEnd", this ._highlightLineEnds.bind(this), false);
207
208 // Register 'eval' shortcut.
209 var isMac = InspectorController.platform().indexOf("mac-") === 0;
210 var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Mod ifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl;
211 var shortcut = WebInspector.KeyboardShortcut.makeKey(69 /* 'E' */, platf ormSpecificModifier | WebInspector.KeyboardShortcut.Modifiers.Shift);
212 this._shortcuts[shortcut] = this._evalSelectionInCallFrame.bind(this);
213
214 var headElement = this.element.contentDocument.getElementsByTagName("hea d")[0];
215 if (!headElement) {
216 headElement = this.element.contentDocument.createElement("head");
217 this.element.contentDocument.documentElement.insertBefore(headElemen t, this.element.contentDocument.documentElement.firstChild);
218 }
219
220 var styleElement = this.element.contentDocument.createElement("style");
221 headElement.appendChild(styleElement);
222
223 // Add these style rules here since they are specific to the Inspector. They also behave oddly and not
224 // all properties apply if added to view-source.css (becuase it is a use r agent sheet.)
225 var styleText = ".webkit-line-number { background-repeat: no-repeat; bac kground-position: right 1px; }\n";
226 styleText += ".webkit-execution-line .webkit-line-number { color: transp arent; background-image: -webkit-canvas(program-counter); }\n";
227
228 styleText += ".webkit-breakpoint .webkit-line-number { color: white; bac kground-image: -webkit-canvas(breakpoint); }\n";
229 styleText += ".webkit-breakpoint-disabled .webkit-line-number { color: w hite; background-image: -webkit-canvas(breakpoint-disabled); }\n";
230 styleText += ".webkit-breakpoint.webkit-execution-line .webkit-line-numb er { color: transparent; background-image: -webkit-canvas(breakpoint-program-cou nter); }\n";
231 styleText += ".webkit-breakpoint-disabled.webkit-execution-line .webkit- line-number { color: transparent; background-image: -webkit-canvas(breakpoint-di sabled-program-counter); }\n";
232
233 styleText += ".webkit-breakpoint.webkit-breakpoint-conditional .webkit-l ine-number { color: white; background-image: -webkit-canvas(breakpoint-condition al); }\n";
234 styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint- disabled-conditional); }\n";
235 styleText += ".webkit-breakpoint.webkit-breakpoint-conditional.webkit-ex ecution-line .webkit-line-number { color: transparent; background-image: -webkit -canvas(breakpoint-conditional-program-counter); }\n";
236 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";
237
238 styleText += ".webkit-execution-line .webkit-line-content { background-c olor: rgb(171, 191, 254); outline: 1px solid rgb(64, 115, 244); }\n";
239 styleText += ".webkit-height-sized-to-fit { overflow-y: hidden }\n";
240 styleText += ".webkit-line-content { background-color: white; }\n";
241 styleText += "@-webkit-keyframes fadeout {from {background-color: rgb(25 5, 255, 120);} to { background-color: white;}}\n";
242 styleText += ".webkit-highlighted-line .webkit-line-content { background -color: rgb(255, 255, 120); -webkit-animation: 'fadeout' 2s 500ms}\n";
243 styleText += ".webkit-javascript-comment { color: rgb(0, 116, 0); }\n";
244 styleText += ".webkit-javascript-keyword { color: rgb(170, 13, 145); }\n ";
245 styleText += ".webkit-javascript-number { color: rgb(28, 0, 207); }\n";
246 styleText += ".webkit-javascript-string, .webkit-javascript-regexp { col or: rgb(196, 26, 22); }\n";
247
248 // 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.
249 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); }";
250 styleText += ".popup-glasspane { position: absolute; top: 0; left: 0; he ight: 100%; width: 100%; opacity: 0; z-index: 9900; }";
251 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; }";
252 styleText += ".popup-content.breakpoint-condition { width: 90%; }";
253 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; }";
254 // This class is already in inspector.css
255 styleText += ".hidden { display: none !important; }";
256
257 styleElement.textContent = styleText;
258
259 this._needsProgramCounterImage = true;
260 this._needsBreakpointImages = true;
261
262 this.element.contentWindow.Element.prototype.addStyleClass = Element.pro totype.addStyleClass;
263 this.element.contentWindow.Element.prototype.removeStyleClass = Element. prototype.removeStyleClass;
264 this.element.contentWindow.Element.prototype.positionAt = Element.protot ype.positionAt;
265 this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses;
266 this.element.contentWindow.Element.prototype.hasStyleClass = Element.pro totype.hasStyleClass;
267 this.element.contentWindow.Element.prototype.pageOffsetRelativeToWindow = Element.prototype.pageOffsetRelativeToWindow;
268 this.element.contentWindow.Element.prototype.__defineGetter__("totalOffs etLeft", Element.prototype.__lookupGetter__("totalOffsetLeft"));
269 this.element.contentWindow.Element.prototype.__defineGetter__("totalOffs etTop", Element.prototype.__lookupGetter__("totalOffsetTop"));
270 this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNam e = Node.prototype.enclosingNodeOrSelfWithNodeName;
271 this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNam eInArray = Node.prototype.enclosingNodeOrSelfWithNodeNameInArray;
272
273 this._addExistingMessagesToSource();
274 this._addExistingBreakpointsToSource();
275 this._updateExecutionLine();
276 if (this._executionLine)
277 this.revealLine(this._executionLine);
278
279 if (this.autoSizesToFitContentHeight)
280 this.sizeToFitContentHeight();
281
282 if (this._lineNumberToReveal) {
283 this.revealLine(this._lineNumberToReveal);
284 delete this._lineNumberToReveal;
285 }
286
287 if (this._lineNumberToHighlight) {
288 this.highlightLine(this._lineNumberToHighlight);
289 delete this._lineNumberToHighlight;
290 }
291
292 this.dispatchEventToListeners("content loaded");
293 },
294
295 _isContentLoaded: function() {
296 var doc = this.element.contentDocument;
297 return doc && doc.getElementsByTagName("table")[0];
298 },
299
300 _windowResized: function(event)
301 {
302 if (!this._autoSizesToFitContentHeight)
303 return;
304 this.sizeToFitContentHeight();
305 },
306
307 _documentContextMenu: function(event)
308 {
309 if (!event.target.hasStyleClass("webkit-line-number"))
310 return;
311 var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
312 if (!sourceRow._breakpointObject && this.addBreakpointDelegate)
313 this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
314
315 var breakpoint = sourceRow._breakpointObject;
316 if (!breakpoint)
317 return;
318
319 this._editBreakpointCondition(event.target, sourceRow, breakpoint);
320 event.preventDefault();
321 },
322
323 _documentMouseDown: function(event)
324 {
325 if (!event.target.hasStyleClass("webkit-line-number"))
326 return;
327 if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
328 return;
329 var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
330 if (sourceRow._breakpointObject && sourceRow._breakpointObject.enabled)
331 sourceRow._breakpointObject.enabled = false;
332 else if (sourceRow._breakpointObject)
333 WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointOb ject);
334 else if (this.addBreakpointDelegate)
335 this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
336 },
337
338 _editBreakpointCondition: function(eventTarget, sourceRow, breakpoint)
339 {
340 // 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.
341 var popupDocument = this.element.contentDocument;
342 this._showBreakpointConditionPopup(eventTarget, breakpoint.line, popupDo cument);
343
344 function committed(element, newText)
345 {
346 breakpoint.condition = newText;
347 if (breakpoint.condition)
348 sourceRow.addStyleClass("webkit-breakpoint-conditional");
349 else
350 sourceRow.removeStyleClass("webkit-breakpoint-conditional");
351 dismissed.call(this);
352 }
353
354 function dismissed()
355 {
356 this._popup.hide();
357 delete this._conditionEditorElement;
358 }
359
360 var dismissedHandler = dismissed.bind(this);
361 this._conditionEditorElement.addEventListener("blur", dismissedHandler, false);
362
363 WebInspector.startEditing(this._conditionEditorElement, committed.bind(t his), dismissedHandler);
364 this._conditionEditorElement.value = breakpoint.condition;
365 this._conditionEditorElement.select();
366 },
367
368 _showBreakpointConditionPopup: function(clickedElement, lineNumber, popupDoc ument)
369 {
370 var popupContentElement = this._createPopupElement(lineNumber, popupDocu ment);
371 var lineElement = clickedElement.enclosingNodeOrSelfWithNodeName("td").n extSibling;
372 if (this._popup) {
373 this._popup.hide();
374 this._popup.element = popupContentElement;
375 } else {
376 this._popup = new WebInspector.Popup(popupContentElement);
377 this._popup.autoHide = true;
378 }
379 this._popup.anchor = lineElement;
380 this._popup.show();
381 },
382
383 _createPopupElement: function(lineNumber, popupDocument)
384 {
385 var popupContentElement = popupDocument.createElement("div");
386 popupContentElement.className = "popup-content breakpoint-condition";
387
388 var labelElement = document.createElement("label");
389 labelElement.className = "popup-message";
390 labelElement.htmlFor = "bp-condition";
391 labelElement.appendChild(document.createTextNode(WebInspector.UIString(" The breakpoint on line %d will stop only if this expression is true:", lineNumbe r)));
392 popupContentElement.appendChild(labelElement);
393
394 var editorElement = document.createElement("input");
395 editorElement.id = "bp-condition";
396 editorElement.type = "text"
397 popupContentElement.appendChild(editorElement);
398 this._conditionEditorElement = editorElement;
399
400 return popupContentElement;
401 },
402
403 _documentKeyDown: function(event)
404 {
405 var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
406 var handler = this._shortcuts[shortcut];
407 if (handler) {
408 handler(event);
409 event.preventDefault();
410 } else {
411 WebInspector.documentKeyDown(event);
412 }
413 },
414
415 _evalSelectionInCallFrame: function(event)
416 {
417 if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
418 return;
419
420 var selection = this.element.contentWindow.getSelection();
421 if (!selection.rangeCount)
422 return;
423
424 var expression = selection.getRangeAt(0).toString().trimWhitespace();
425 WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, fals e, function(result, exception) {
426 WebInspector.showConsole();
427 var commandMessage = new WebInspector.ConsoleCommand(expression);
428 WebInspector.console.addMessage(commandMessage);
429 WebInspector.console.addMessage(new WebInspector.ConsoleCommandResul t(result, exception, commandMessage));
430 });
431 },
432
433 _breakpointEnableChanged: function(event)
434 {
435 var breakpoint = event.target;
436 var sourceRow = this.sourceRow(breakpoint.line);
437 if (!sourceRow)
438 return;
439
440 sourceRow.addStyleClass("webkit-breakpoint");
441
442 if (breakpoint.enabled)
443 sourceRow.removeStyleClass("webkit-breakpoint-disabled");
444 else
445 sourceRow.addStyleClass("webkit-breakpoint-disabled");
446 },
447
448 _updateExecutionLine: function(previousLine)
449 {
450 if (previousLine) {
451 var sourceRow = this.sourceRow(previousLine);
452 if (sourceRow)
453 sourceRow.removeStyleClass("webkit-execution-line");
454 }
455
456 if (!this._executionLine)
457 return;
458
459 this._drawProgramCounterImageIfNeeded();
460
461 var sourceRow = this.sourceRow(this._executionLine);
462 if (sourceRow)
463 sourceRow.addStyleClass("webkit-execution-line");
464 },
465
466 _addExistingBreakpointsToSource: function()
467 {
468 var length = this.breakpoints.length;
469 for (var i = 0; i < length; ++i)
470 this._addBreakpointToSource(this.breakpoints[i]);
471 },
472
473 _addBreakpointToSource: function(breakpoint)
474 {
475 var sourceRow = this.sourceRow(breakpoint.line);
476 if (!sourceRow)
477 return;
478
479 breakpoint.sourceText = sourceRow.getElementsByClassName('webkit-line-co ntent')[0].textContent;
480
481 this._drawBreakpointImagesIfNeeded();
482
483 sourceRow._breakpointObject = breakpoint;
484
485 sourceRow.addStyleClass("webkit-breakpoint");
486 if (!breakpoint.enabled)
487 sourceRow.addStyleClass("webkit-breakpoint-disabled");
488 if (breakpoint.condition)
489 sourceRow.addStyleClass("webkit-breakpoint-conditional");
490 },
491
492 _removeBreakpointFromSource: function(breakpoint)
493 {
494 var sourceRow = this.sourceRow(breakpoint.line);
495 if (!sourceRow)
496 return;
497
498 delete sourceRow._breakpointObject;
499
500 sourceRow.removeStyleClass("webkit-breakpoint");
501 sourceRow.removeStyleClass("webkit-breakpoint-disabled");
502 sourceRow.removeStyleClass("webkit-breakpoint-conditional");
503 },
504
505 _incrementMessageRepeatCount: function(msg, repeatDelta)
506 {
507 if (!msg._resourceMessageLineElement)
508 return;
509
510 if (!msg._resourceMessageRepeatCountElement) {
511 var repeatedElement = document.createElement("span");
512 msg._resourceMessageLineElement.appendChild(repeatedElement);
513 msg._resourceMessageRepeatCountElement = repeatedElement;
514 }
515
516 msg.repeatCount += repeatDelta;
517 msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIStri ng(" (repeated %d times)", msg.repeatCount);
518 },
519
520 _addExistingMessagesToSource: function()
521 {
522 var length = this.messages.length;
523 for (var i = 0; i < length; ++i)
524 this._addMessageToSource(this.messages[i]);
525 },
526
527 _addMessageToSource: function(msg)
528 {
529 var row = this.sourceRow(msg.line);
530 if (!row)
531 return;
532
533 var cell = row.cells[1];
534 if (!cell)
535 return;
536
537 var messageBubbleElement = cell.lastChild;
538 if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEM ENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) {
539 messageBubbleElement = this.element.contentDocument.createElement("d iv");
540 messageBubbleElement.className = "webkit-html-message-bubble";
541 cell.appendChild(messageBubbleElement);
542 }
543
544 if (!row.messages)
545 row.messages = [];
546
547 for (var i = 0; i < row.messages.length; ++i) {
548 if (row.messages[i].isEqual(msg, true)) {
549 this._incrementMessageRepeatCount(row.messages[i], msg.repeatDel ta);
550 return;
551 }
552 }
553
554 row.messages.push(msg);
555
556 var imageURL;
557 switch (msg.level) {
558 case WebInspector.ConsoleMessage.MessageLevel.Error:
559 messageBubbleElement.addStyleClass("webkit-html-error-message");
560 imageURL = "Images/errorIcon.png";
561 break;
562 case WebInspector.ConsoleMessage.MessageLevel.Warning:
563 messageBubbleElement.addStyleClass("webkit-html-warning-message" );
564 imageURL = "Images/warningIcon.png";
565 break;
566 }
567
568 var messageLineElement = this.element.contentDocument.createElement("div ");
569 messageLineElement.className = "webkit-html-message-line";
570 messageBubbleElement.appendChild(messageLineElement);
571
572 // Create the image element in the Inspector's document so we can use re lative image URLs.
573 var image = document.createElement("img");
574 image.src = imageURL;
575 image.className = "webkit-html-message-icon";
576
577 // Adopt the image element since it wasn't created in element's contentD ocument.
578 image = this.element.contentDocument.adoptNode(image);
579 messageLineElement.appendChild(image);
580 messageLineElement.appendChild(this.element.contentDocument.createTextNo de(msg.message));
581
582 msg._resourceMessageLineElement = messageLineElement;
583 },
584
585 _drawProgramCounterInContext: function(ctx, glow)
586 {
587 if (glow)
588 ctx.save();
589
590 ctx.beginPath();
591 ctx.moveTo(17, 2);
592 ctx.lineTo(19, 2);
593 ctx.lineTo(19, 0);
594 ctx.lineTo(21, 0);
595 ctx.lineTo(26, 5.5);
596 ctx.lineTo(21, 11);
597 ctx.lineTo(19, 11);
598 ctx.lineTo(19, 9);
599 ctx.lineTo(17, 9);
600 ctx.closePath();
601 ctx.fillStyle = "rgb(142, 5, 4)";
602
603 if (glow) {
604 ctx.shadowBlur = 4;
605 ctx.shadowColor = "rgb(255, 255, 255)";
606 ctx.shadowOffsetX = -1;
607 ctx.shadowOffsetY = 0;
608 }
609
610 ctx.fill();
611 ctx.fill(); // Fill twice to get a good shadow and darker anti-aliased p ixels.
612
613 if (glow)
614 ctx.restore();
615 },
616
617 _drawProgramCounterImageIfNeeded: function()
618 {
619 if (!this._needsProgramCounterImage || !this.element.contentDocument)
620 return;
621
622 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "progra m-counter", 26, 11);
623 ctx.clearRect(0, 0, 26, 11);
624 this._drawProgramCounterInContext(ctx, true);
625
626 delete this._needsProgramCounterImage;
627 },
628
629 _drawBreakpointImagesIfNeeded: function(conditional)
630 {
631 if (!this._needsBreakpointImages || !this.element.contentDocument)
632 return;
633
634 function drawBreakpoint(ctx, disabled, conditional)
635 {
636 ctx.beginPath();
637 ctx.moveTo(0, 2);
638 ctx.lineTo(2, 0);
639 ctx.lineTo(21, 0);
640 ctx.lineTo(26, 5.5);
641 ctx.lineTo(21, 11);
642 ctx.lineTo(2, 11);
643 ctx.lineTo(0, 9);
644 ctx.closePath();
645 ctx.fillStyle = conditional ? "rgb(217, 142, 1)" : "rgb(1, 142, 217) ";
646 ctx.strokeStyle = conditional ? "rgb(205, 103, 0)" : "rgb(0, 103, 20 5)";
647 ctx.lineWidth = 3;
648 ctx.fill();
649 ctx.save();
650 ctx.clip();
651 ctx.stroke();
652 ctx.restore();
653
654 if (!disabled)
655 return;
656
657 ctx.save();
658 ctx.globalCompositeOperation = "destination-out";
659 ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
660 ctx.fillRect(0, 0, 26, 11);
661 ctx.restore();
662 }
663
664
665 // Unconditional breakpoints.
666
667 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint", 26, 11);
668 ctx.clearRect(0, 0, 26, 11);
669 drawBreakpoint(ctx);
670
671 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-program-counter", 26, 11);
672 ctx.clearRect(0, 0, 26, 11);
673 drawBreakpoint(ctx);
674 ctx.clearRect(20, 0, 6, 11);
675 this._drawProgramCounterInContext(ctx, true);
676
677 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-disabled", 26, 11);
678 ctx.clearRect(0, 0, 26, 11);
679 drawBreakpoint(ctx, true);
680
681 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-disabled-program-counter", 26, 11);
682 ctx.clearRect(0, 0, 26, 11);
683 drawBreakpoint(ctx, true);
684 ctx.clearRect(20, 0, 6, 11);
685 this._drawProgramCounterInContext(ctx, true);
686
687
688 // Conditional breakpoints.
689
690 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-conditional", 26, 11);
691 ctx.clearRect(0, 0, 26, 11);
692 drawBreakpoint(ctx, false, true);
693
694 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-conditional-program-counter", 26, 11);
695 ctx.clearRect(0, 0, 26, 11);
696 drawBreakpoint(ctx, false, true);
697 ctx.clearRect(20, 0, 6, 11);
698 this._drawProgramCounterInContext(ctx, true);
699
700 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-disabled-conditional", 26, 11);
701 ctx.clearRect(0, 0, 26, 11);
702 drawBreakpoint(ctx, true, true);
703
704 var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakp oint-disabled-conditional-program-counter", 26, 11);
705 ctx.clearRect(0, 0, 26, 11);
706 drawBreakpoint(ctx, true, true);
707 ctx.clearRect(20, 0, 6, 11);
708 this._drawProgramCounterInContext(ctx, true);
709
710 delete this._needsBreakpointImages;
711 },
712
713 syntaxHighlightJavascript: function()
714 {
715 var table = this.element.contentDocument.getElementsByTagName("table")[0 ];
716 if (!table)
717 return;
718
719 function deleteContinueFlags(cell)
720 {
721 if (!cell)
722 return;
723 delete cell._commentContinues;
724 delete cell._singleQuoteStringContinues;
725 delete cell._doubleQuoteStringContinues;
726 delete cell._regexpContinues;
727 }
728
729 function createSpan(content, className)
730 {
731 var span = document.createElement("span");
732 span.className = className;
733 span.appendChild(document.createTextNode(content));
734 return span;
735 }
736
737 function generateFinder(regex, matchNumber, className)
738 {
739 return function(str) {
740 var match = regex.exec(str);
741 if (!match)
742 return null;
743 previousMatchLength = match[matchNumber].length;
744 return createSpan(match[matchNumber], className);
745 };
746 }
747
748 var findNumber = generateFinder(/^(-?(\d+\.?\d*([eE][+-]\d+)?|0[xX]\h+|I nfinity)|NaN)(?:\W|$)/, 1, "webkit-javascript-number");
749 var findKeyword = generateFinder(/^(null|true|false|break|case|catch|con st|default|finally|for|instanceof|new|var|continue|function|return|void|delete|i f|this|do|while|else|in|switch|throw|try|typeof|with|debugger|class|enum|export| extends|import|super|get|set)(?:\W|$)/, 1, "webkit-javascript-keyword");
750 var findSingleLineString = generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\]| \\.)*'/, 0, "webkit-javascript-string"); // " this quote keeps Xcode happy
751 var findMultilineCommentStart = generateFinder(/^\/\*.*$/, 0, "webkit-ja vascript-comment");
752 var findMultilineCommentEnd = generateFinder(/^.*?\*\//, 0, "webkit-java script-comment");
753 var findMultilineSingleQuoteStringStart = generateFinder(/^'(?:[^'\\]|\\ .)*\\$/, 0, "webkit-javascript-string");
754 var findMultilineSingleQuoteStringEnd = generateFinder(/^(?:[^'\\]|\\.)* ?'/, 0, "webkit-javascript-string");
755 var findMultilineDoubleQuoteStringStart = generateFinder(/^"(?:[^"\\]|\\ .)*\\$/, 0, "webkit-javascript-string");
756 var findMultilineDoubleQuoteStringEnd = generateFinder(/^(?:[^"\\]|\\.)* ?"/, 0, "webkit-javascript-string");
757 var findMultilineRegExpEnd = generateFinder(/^(?:[^\/\\]|\\.)*?\/([gim]{ 0,3})/, 0, "webkit-javascript-regexp");
758 var findSingleLineComment = generateFinder(/^\/\/.*|^\/\*.*?\*\//, 0, "w ebkit-javascript-comment");
759
760 function findMultilineRegExpStart(str)
761 {
762 var match = /^\/(?:[^\/\\]|\\.)*\\$/.exec(str);
763 if (!match || !/\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[0]))
764 return null;
765 var node = createSpan(match[0], "webkit-javascript-regexp");
766 previousMatchLength = match[0].length;
767 return node;
768 }
769
770 function findSingleLineRegExp(str)
771 {
772 var match = /^(\/(?:[^\/\\]|\\.)*\/([gim]{0,3}))(.?)/.exec(str);
773 if (!match || !(match[2].length > 0 || /\\|\$|\.[\?\*\+]|[^\|]\|[^\| ]/.test(match[1]) || /\.|;|,/.test(match[3])))
774 return null;
775 var node = createSpan(match[1], "webkit-javascript-regexp");
776 previousMatchLength = match[1].length;
777 return node;
778 }
779
780 function syntaxHighlightJavascriptLine(line, prevLine)
781 {
782 var messageBubble = line.lastChild;
783 if (messageBubble && messageBubble.nodeType === Node.ELEMENT_NODE && messageBubble.hasStyleClass("webkit-html-message-bubble"))
784 line.removeChild(messageBubble);
785 else
786 messageBubble = null;
787
788 var code = line.textContent;
789
790 while (line.firstChild)
791 line.removeChild(line.firstChild);
792
793 var token;
794 var tmp = 0;
795 var i = 0;
796 previousMatchLength = 0;
797
798 if (prevLine) {
799 if (prevLine._commentContinues) {
800 if (!(token = findMultilineCommentEnd(code))) {
801 token = createSpan(code, "webkit-javascript-comment");
802 line._commentContinues = true;
803 }
804 } else if (prevLine._singleQuoteStringContinues) {
805 if (!(token = findMultilineSingleQuoteStringEnd(code))) {
806 token = createSpan(code, "webkit-javascript-string");
807 line._singleQuoteStringContinues = true;
808 }
809 } else if (prevLine._doubleQuoteStringContinues) {
810 if (!(token = findMultilineDoubleQuoteStringEnd(code))) {
811 token = createSpan(code, "webkit-javascript-string");
812 line._doubleQuoteStringContinues = true;
813 }
814 } else if (prevLine._regexpContinues) {
815 if (!(token = findMultilineRegExpEnd(code))) {
816 token = createSpan(code, "webkit-javascript-regexp");
817 line._regexpContinues = true;
818 }
819 }
820 if (token) {
821 i += previousMatchLength ? previousMatchLength : code.length ;
822 tmp = i;
823 line.appendChild(token);
824 }
825 }
826
827 for ( ; i < code.length; ++i) {
828 var codeFragment = code.substr(i);
829 var prevChar = code[i - 1];
830 token = findSingleLineComment(codeFragment);
831 if (!token) {
832 if ((token = findMultilineCommentStart(codeFragment)))
833 line._commentContinues = true;
834 else if (!prevChar || /^\W/.test(prevChar)) {
835 token = findNumber(codeFragment, code[i - 1]) ||
836 findKeyword(codeFragment, code[i - 1]) ||
837 findSingleLineString(codeFragment) ||
838 findSingleLineRegExp(codeFragment);
839 if (!token) {
840 if (token = findMultilineSingleQuoteStringStart(code Fragment))
841 line._singleQuoteStringContinues = true;
842 else if (token = findMultilineDoubleQuoteStringStart (codeFragment))
843 line._doubleQuoteStringContinues = true;
844 else if (token = findMultilineRegExpStart(codeFragme nt))
845 line._regexpContinues = true;
846 }
847 }
848 }
849
850 if (token) {
851 if (tmp !== i)
852 line.appendChild(document.createTextNode(code.substring( tmp, i)));
853 line.appendChild(token);
854 i += previousMatchLength - 1;
855 tmp = i + 1;
856 }
857 }
858
859 if (tmp < code.length)
860 line.appendChild(document.createTextNode(code.substring(tmp, i)) );
861
862 if (messageBubble)
863 line.appendChild(messageBubble);
864 }
865
866 var i = 0;
867 var rows = table.rows;
868 var rowsLength = rows.length;
869 var previousCell = null;
870 var previousMatchLength = 0;
871 var sourceFrame = this;
872
873 // Split up the work into chunks so we don't block the
874 // UI thread while processing.
875
876 function processChunk()
877 {
878 for (var end = Math.min(i + 10, rowsLength); i < end; ++i) {
879 var row = rows[i];
880 if (!row)
881 continue;
882 var cell = row.cells[1];
883 if (!cell)
884 continue;
885 syntaxHighlightJavascriptLine(cell, previousCell);
886 if (i < (end - 1))
887 deleteContinueFlags(previousCell);
888 previousCell = cell;
889 }
890
891 if (i >= rowsLength && processChunkInterval) {
892 deleteContinueFlags(previousCell);
893 clearInterval(processChunkInterval);
894
895 sourceFrame.dispatchEventToListeners("syntax highlighting comple te");
896 }
897 }
898
899 processChunk();
900
901 var processChunkInterval = setInterval(processChunk, 25);
902 }
903 }
904
905 WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype;
906
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698