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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js

Issue 2747553002: [DevTools] Rework Popover API (Closed)
Patch Set: rebased Created 3 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 26 matching lines...) Expand all
37 */ 37 */
38 constructor(uiSourceCode) { 38 constructor(uiSourceCode) {
39 super(uiSourceCode); 39 super(uiSourceCode);
40 this._debuggerSourceCode = uiSourceCode; 40 this._debuggerSourceCode = uiSourceCode;
41 41
42 this._scriptsPanel = Sources.SourcesPanel.instance(); 42 this._scriptsPanel = Sources.SourcesPanel.instance();
43 this._breakpointManager = Bindings.breakpointManager; 43 this._breakpointManager = Bindings.breakpointManager;
44 if (uiSourceCode.project().type() === Workspace.projectTypes.Debugger) 44 if (uiSourceCode.project().type() === Workspace.projectTypes.Debugger)
45 this.element.classList.add('source-frame-debugger-script'); 45 this.element.classList.add('source-frame-debugger-script');
46 46
47 this._popoverHelper = new UI.PopoverHelper(this._scriptsPanel.element, true) ; 47 this._popoverHelper = new UI.PopoverHelper(this._scriptsPanel.element, this. _getPopoverRequest.bind(this));
48 this._popoverHelper.initializeCallbacks( 48 this._popoverHelper.setDisableOnClick(true);
49 this._getPopoverAnchor.bind(this), this._showObjectPopover.bind(this), t his._onHidePopover.bind(this));
50 this._popoverHelper.setTimeout(250, 250); 49 this._popoverHelper.setTimeout(250, 250);
51 this._popoverHelper.setHasPadding(true); 50 this._popoverHelper.setHasPadding(true);
52 this._scriptsPanel.element.addEventListener( 51 this._scriptsPanel.element.addEventListener(
53 'scroll', this._popoverHelper.hidePopover.bind(this._popoverHelper), tru e); 52 'scroll', this._popoverHelper.hidePopover.bind(this._popoverHelper), tru e);
54 53
55 this.textEditor.element.addEventListener('keydown', this._onKeyDown.bind(thi s), true); 54 this.textEditor.element.addEventListener('keydown', this._onKeyDown.bind(thi s), true);
56 55
57 this.textEditor.addEventListener( 56 this.textEditor.addEventListener(
58 SourceFrame.SourcesTextEditor.Events.GutterClick, this._handleGutterClic k.bind(this), this); 57 SourceFrame.SourcesTextEditor.Events.GutterClick, this._handleGutterClic k.bind(this), this);
59 58
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 } 368 }
370 369
371 /** 370 /**
372 * @param {string} tokenType 371 * @param {string} tokenType
373 * @return {boolean} 372 * @return {boolean}
374 */ 373 */
375 _isIdentifier(tokenType) { 374 _isIdentifier(tokenType) {
376 return tokenType.startsWith('js-variable') || tokenType.startsWith('js-prope rty') || tokenType === 'js-def'; 375 return tokenType.startsWith('js-variable') || tokenType.startsWith('js-prope rty') || tokenType === 'js-def';
377 } 376 }
378 377
379 _getPopoverAnchor(element, event) { 378 /**
379 * @param {!Event} event
380 * @return {?UI.PopoverRequest}
381 */
382 _getPopoverRequest(event) {
380 var target = UI.context.flavor(SDK.Target); 383 var target = UI.context.flavor(SDK.Target);
381 var debuggerModel = target ? target.model(SDK.DebuggerModel) : null; 384 var debuggerModel = target ? target.model(SDK.DebuggerModel) : null;
382 if (!debuggerModel || !debuggerModel.isPaused()) 385 if (!debuggerModel || !debuggerModel.isPaused())
383 return; 386 return null;
384 387
385 var textPosition = this.textEditor.coordinatesToCursorPosition(event.x, even t.y); 388 var textPosition = this.textEditor.coordinatesToCursorPosition(event.x, even t.y);
386 if (!textPosition) 389 if (!textPosition)
387 return; 390 return null;
391
388 var mouseLine = textPosition.startLine; 392 var mouseLine = textPosition.startLine;
389 var mouseColumn = textPosition.startColumn; 393 var mouseColumn = textPosition.startColumn;
390 var textSelection = this.textEditor.selection().normalize(); 394 var textSelection = this.textEditor.selection().normalize();
395 var anchorBox;
396 var lineNumber;
397 var startHighlight;
398 var endHighlight;
399
391 if (textSelection && !textSelection.isEmpty()) { 400 if (textSelection && !textSelection.isEmpty()) {
392 if (textSelection.startLine !== textSelection.endLine || textSelection.sta rtLine !== mouseLine || 401 if (textSelection.startLine !== textSelection.endLine || textSelection.sta rtLine !== mouseLine ||
393 mouseColumn < textSelection.startColumn || mouseColumn > textSelection .endColumn) 402 mouseColumn < textSelection.startColumn || mouseColumn > textSelection .endColumn)
394 return; 403 return null;
395 404
396 var leftCorner = this.textEditor.cursorPositionToCoordinates(textSelection .startLine, textSelection.startColumn); 405 var leftCorner = this.textEditor.cursorPositionToCoordinates(textSelection .startLine, textSelection.startColumn);
397 var rightCorner = this.textEditor.cursorPositionToCoordinates(textSelectio n.endLine, textSelection.endColumn); 406 var rightCorner = this.textEditor.cursorPositionToCoordinates(textSelectio n.endLine, textSelection.endColumn);
398 var anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height); 407 anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - left Corner.x, leftCorner.height);
399 anchorBox.highlight = { 408 lineNumber = textSelection.startLine;
400 lineNumber: textSelection.startLine, 409 startHighlight = textSelection.startColumn;
401 startColumn: textSelection.startColumn, 410 endHighlight = textSelection.endColumn - 1;
402 endColumn: textSelection.endColumn - 1 411 } else {
403 }; 412 var token = this.textEditor.tokenAtTextPosition(textPosition.startLine, te xtPosition.startColumn);
404 anchorBox.forSelection = true; 413 if (!token || !token.type)
405 return anchorBox; 414 return null;
415 lineNumber = textPosition.startLine;
416 var line = this.textEditor.line(lineNumber);
417 var tokenContent = line.substring(token.startColumn, token.endColumn);
418
419 var isIdentifier = this._isIdentifier(token.type);
420 if (!isIdentifier && (token.type !== 'js-keyword' || tokenContent !== 'thi s'))
421 return null;
422
423 var leftCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, t oken.startColumn);
424 var rightCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.endColumn - 1);
425 anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - left Corner.x, leftCorner.height);
426
427 startHighlight = token.startColumn;
428 endHighlight = token.endColumn - 1;
429 while (startHighlight > 1 && line.charAt(startHighlight - 1) === '.') {
430 var tokenBefore = this.textEditor.tokenAtTextPosition(lineNumber, startH ighlight - 2);
431 if (!tokenBefore || !tokenBefore.type)
432 return null;
433 startHighlight = tokenBefore.startColumn;
434 }
406 } 435 }
407 436
408 var token = this.textEditor.tokenAtTextPosition(textPosition.startLine, text Position.startColumn); 437 var objectPopoverHelper;
409 if (!token || !token.type) 438 var highlightDescriptor;
410 return;
411 var lineNumber = textPosition.startLine;
412 var line = this.textEditor.line(lineNumber);
413 var tokenContent = line.substring(token.startColumn, token.endColumn);
414 439
415 var isIdentifier = this._isIdentifier(token.type); 440 return {
416 if (!isIdentifier && (token.type !== 'js-keyword' || tokenContent !== 'this' )) 441 box: anchorBox,
417 return; 442 show: async popover => {
418 443 var selectedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
419 var leftCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, tok en.startColumn); 444 if (!selectedCallFrame)
420 var rightCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, to ken.endColumn - 1); 445 return false;
421 var anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - le ftCorner.x, leftCorner.height); 446 var evaluationText = this.textEditor.line(lineNumber).substring(startHig hlight, endHighlight + 1);
422 447 var resolvedText = await Sources.SourceMapNamesResolver.resolveExpressio n(
423 anchorBox.highlight = {lineNumber: lineNumber, startColumn: token.startColum n, endColumn: token.endColumn - 1}; 448 selectedCallFrame, evaluationText, this._debuggerSourceCode, lineNum ber, startHighlight, endHighlight);
424 449 var remoteObject = await selectedCallFrame.evaluatePromise(
425 return anchorBox; 450 resolvedText || evaluationText, 'popover', false, true, false, false );
426 } 451 if (!remoteObject)
427 452 return false;
428 /** 453 objectPopoverHelper = await ObjectUI.ObjectPopoverHelper.buildObjectPopo ver(remoteObject, popover);
429 * @param {!AnchorBox} anchorBox 454 var potentiallyUpdatedCallFrame = UI.context.flavor(SDK.DebuggerModel.Ca llFrame);
430 * @return {!Promise<?SDK.RemoteObject>} 455 if (!objectPopoverHelper || selectedCallFrame !== potentiallyUpdatedCall Frame) {
431 */ 456 target.runtimeModel.releaseObjectGroup('popover');
432 _resolveObjectForPopover(anchorBox) { 457 if (objectPopoverHelper)
433 var selectedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame); 458 objectPopoverHelper.dispose();
434 if (!selectedCallFrame)
435 return Promise.resolve(/** @type {?SDK.RemoteObject} */ (null));
436 var lineNumber = anchorBox.highlight.lineNumber;
437 var startHighlight = anchorBox.highlight.startColumn;
438 var endHighlight = anchorBox.highlight.endColumn;
439 var line = this.textEditor.line(lineNumber);
440 if (!anchorBox.forSelection) {
441 while (startHighlight > 1 && line.charAt(startHighlight - 1) === '.') {
442 var token = this.textEditor.tokenAtTextPosition(lineNumber, startHighlig ht - 2);
443 if (!token || !token.type)
444 return Promise.resolve(/** @type {?SDK.RemoteObject} */ (null));
445 startHighlight = token.startColumn;
446 }
447 }
448 var evaluationText = line.substring(startHighlight, endHighlight + 1);
449 return Sources.SourceMapNamesResolver
450 .resolveExpression(
451 selectedCallFrame, evaluationText, this._debuggerSourceCode, lineNum ber, startHighlight, endHighlight)
452 .then(onResolve.bind(this));
453
454 /**
455 * @param {?string=} text
456 * @return {!Promise<?SDK.RemoteObject>}
457 * @this {Sources.JavaScriptSourceFrame}
458 */
459 function onResolve(text) {
460 var fulfill;
461 var promise = new Promise(x => fulfill = x);
462 selectedCallFrame.evaluate(
463 text || evaluationText, 'popover', false, true, false, false, showObje ctPopover.bind(this, fulfill));
464 return promise;
465 }
466
467 /**
468 * @param {function(?SDK.RemoteObject)} fulfill
469 * @param {?Protocol.Runtime.RemoteObject} result
470 * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
471 * @this {Sources.JavaScriptSourceFrame}
472 */
473 function showObjectPopover(fulfill, result, exceptionDetails) {
474 var target = UI.context.flavor(SDK.Target);
475 var potentiallyUpdatedCallFrame = UI.context.flavor(SDK.DebuggerModel.Call Frame);
476 if (selectedCallFrame !== potentiallyUpdatedCallFrame || !result || except ionDetails) {
477 fulfill(null);
478 return;
479 }
480 this._popoverAnchorBox = anchorBox;
481 this._popoverTarget = target;
482 var highlightRange = new Common.TextRange(lineNumber, startHighlight, line Number, endHighlight);
483 this._popoverAnchorBox._highlightDescriptor =
484 this.textEditor.highlightRange(highlightRange, 'source-frame-eval-expr ession');
485 fulfill(target.runtimeModel.createRemoteObject(result));
486 }
487 }
488
489 /**
490 * @param {!AnchorBox|!Element} anchorBox
491 * @param {!UI.GlassPane} popover
492 * @return {!Promise<boolean>}
493 */
494 _showObjectPopover(anchorBox, popover) {
495 return this._resolveObjectForPopover(/** @type {!AnchorBox} */ (anchorBox)). then(object => {
496 if (!object)
497 return false;
498 return ObjectUI.ObjectPopoverHelper.buildObjectPopover(object, popover).th en(objectPopoverHelper => {
499 if (!objectPopoverHelper) {
500 this._onHidePopover(); // Cleanup artifacts from _resolveObjectForPop over.
501 return false; 459 return false;
502 } 460 }
503 this._objectPopoverHelper = objectPopoverHelper; 461 var highlightRange = new Common.TextRange(lineNumber, startHighlight, li neNumber, endHighlight);
462 highlightDescriptor = this.textEditor.highlightRange(highlightRange, 'so urce-frame-eval-expression');
504 return true; 463 return true;
505 }); 464 },
506 }); 465 hide: () => {
507 } 466 objectPopoverHelper.dispose();
508 467 target.runtimeModel.releaseObjectGroup('popover');
509 _onHidePopover() { 468 this.textEditor.removeHighlight(highlightDescriptor);
510 if (this._objectPopoverHelper) { 469 }
511 this._objectPopoverHelper.dispose(); 470 };
512 delete this._objectPopoverHelper;
513 }
514 if (this._popoverTarget) {
515 this._popoverTarget.runtimeModel.releaseObjectGroup('popover');
516 delete this._popoverTarget;
517 }
518 if (this._popoverAnchorBox) {
519 if (this._popoverAnchorBox._highlightDescriptor)
520 this.textEditor.removeHighlight(this._popoverAnchorBox._highlightDescrip tor);
521 delete this._popoverAnchorBox;
522 }
523 } 471 }
524 472
525 _onKeyDown(event) { 473 _onKeyDown(event) {
526 if (event.key === 'Escape') { 474 if (event.key === 'Escape') {
527 if (this._popoverHelper.isPopoverVisible()) { 475 if (this._popoverHelper.isPopoverVisible()) {
528 this._popoverHelper.hidePopover(); 476 this._popoverHelper.hidePopover();
529 event.consume(); 477 event.consume();
530 } 478 }
531 } 479 }
532 } 480 }
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 return; 1452 return;
1505 this.bookmark.clear(); 1453 this.bookmark.clear();
1506 this.bookmark = null; 1454 this.bookmark = null;
1507 } 1455 }
1508 }; 1456 };
1509 1457
1510 Sources.JavaScriptSourceFrame.BreakpointDecoration.bookmarkSymbol = Symbol('book mark'); 1458 Sources.JavaScriptSourceFrame.BreakpointDecoration.bookmarkSymbol = Symbol('book mark');
1511 Sources.JavaScriptSourceFrame.BreakpointDecoration._elementSymbolForTest = Symbo l('element'); 1459 Sources.JavaScriptSourceFrame.BreakpointDecoration._elementSymbolForTest = Symbo l('element');
1512 1460
1513 Sources.JavaScriptSourceFrame.continueToLocationDecorationSymbol = Symbol('bookm ark'); 1461 Sources.JavaScriptSourceFrame.continueToLocationDecorationSymbol = Symbol('bookm ark');
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698