| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 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 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 return; | 574 return; |
| 575 } | 575 } |
| 576 callback(this.runtimeModel.createRemoteObject(result), exceptionDetails); | 576 callback(this.runtimeModel.createRemoteObject(result), exceptionDetails); |
| 577 } | 577 } |
| 578 this.target().runtimeAgent().evaluate( | 578 this.target().runtimeAgent().evaluate( |
| 579 expression, objectGroup, includeCommandLineAPI, silent, this.id, returnB
yValue, generatePreview, userGesture, | 579 expression, objectGroup, includeCommandLineAPI, silent, this.id, returnB
yValue, generatePreview, userGesture, |
| 580 false, evalCallback.bind(this)); | 580 false, evalCallback.bind(this)); |
| 581 } | 581 } |
| 582 | 582 |
| 583 /** | 583 /** |
| 584 * @param {string} expressionString | |
| 585 * @param {string} prefix | |
| 586 * @param {boolean=} force | |
| 587 * @return {!Promise<!Array<string>>} | |
| 588 */ | |
| 589 completionsForExpression(expressionString, prefix, force) { | |
| 590 var lastIndex = expressionString.length - 1; | |
| 591 | |
| 592 var dotNotation = (expressionString[lastIndex] === '.'); | |
| 593 var bracketNotation = (expressionString[lastIndex] === '['); | |
| 594 | |
| 595 if (dotNotation || bracketNotation) | |
| 596 expressionString = expressionString.substr(0, lastIndex); | |
| 597 | |
| 598 // User is entering float value, do not suggest anything. | |
| 599 if (expressionString && !isNaN(expressionString)) | |
| 600 return Promise.resolve([]); | |
| 601 | |
| 602 if (!prefix && !expressionString && !force) | |
| 603 return Promise.resolve([]); | |
| 604 | |
| 605 var fufill; | |
| 606 var promise = new Promise(x => fufill = x); | |
| 607 if (!expressionString && this.debuggerModel.selectedCallFrame()) | |
| 608 this.debuggerModel.selectedCallFrame().variableNames(receivedPropertyNames
.bind(this)); | |
| 609 else | |
| 610 this.evaluate(expressionString, 'completion', true, true, false, false, fa
lse, evaluated.bind(this)); | |
| 611 | |
| 612 return promise; | |
| 613 /** | |
| 614 * @param {?WebInspector.RemoteObject} result | |
| 615 * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails | |
| 616 * @this {WebInspector.ExecutionContext} | |
| 617 */ | |
| 618 function evaluated(result, exceptionDetails) { | |
| 619 if (!result || !!exceptionDetails) { | |
| 620 fufill([]); | |
| 621 return; | |
| 622 } | |
| 623 | |
| 624 /** | |
| 625 * @param {?WebInspector.RemoteObject} object | |
| 626 * @return {!Promise<?WebInspector.RemoteObject>} | |
| 627 */ | |
| 628 function extractTarget(object) { | |
| 629 if (!object) | |
| 630 return Promise.resolve(/** @type {?WebInspector.RemoteObject} */ (null
)); | |
| 631 if (object.type !== 'object' || object.subtype !== 'proxy') | |
| 632 return Promise.resolve(/** @type {?WebInspector.RemoteObject} */ (obje
ct)); | |
| 633 return object.getOwnPropertiesPromise().then(extractTargetFromProperties
).then(extractTarget); | |
| 634 } | |
| 635 | |
| 636 /** | |
| 637 * @param {!{properties: ?Array<!WebInspector.RemoteObjectProperty>, inter
nalProperties: ?Array<!WebInspector.RemoteObjectProperty>}} properties | |
| 638 * @return {?WebInspector.RemoteObject} | |
| 639 */ | |
| 640 function extractTargetFromProperties(properties) { | |
| 641 var internalProperties = properties.internalProperties || []; | |
| 642 var target = internalProperties.find(property => property.name === '[[Ta
rget]]'); | |
| 643 return target ? target.value : null; | |
| 644 } | |
| 645 | |
| 646 /** | |
| 647 * @param {string=} type | |
| 648 * @return {!Object} | |
| 649 * @suppressReceiverCheck | |
| 650 * @this {Object} | |
| 651 */ | |
| 652 function getCompletions(type) { | |
| 653 var object; | |
| 654 if (type === 'string') | |
| 655 object = new String(''); | |
| 656 else if (type === 'number') | |
| 657 object = new Number(0); | |
| 658 else if (type === 'boolean') | |
| 659 object = new Boolean(false); | |
| 660 else | |
| 661 object = this; | |
| 662 | |
| 663 var resultSet = {__proto__: null}; | |
| 664 try { | |
| 665 for (var o = object; o; o = Object.getPrototypeOf(o)) { | |
| 666 if ((type === 'array' || type === 'typedarray') && o === object && A
rrayBuffer.isView(o) && o.length > 9999) | |
| 667 continue; | |
| 668 var names = Object.getOwnPropertyNames(o); | |
| 669 var isArray = Array.isArray(o); | |
| 670 for (var i = 0; i < names.length; ++i) { | |
| 671 // Skip array elements indexes. | |
| 672 if (isArray && /^[0-9]/.test(names[i])) | |
| 673 continue; | |
| 674 resultSet[names[i]] = true; | |
| 675 } | |
| 676 } | |
| 677 } catch (e) { | |
| 678 } | |
| 679 return resultSet; | |
| 680 } | |
| 681 | |
| 682 /** | |
| 683 * @param {?WebInspector.RemoteObject} object | |
| 684 * @this {WebInspector.ExecutionContext} | |
| 685 */ | |
| 686 function completionsForObject(object) { | |
| 687 if (!object) | |
| 688 receivedPropertyNames.call(this, null); | |
| 689 else if (object.type === 'object' || object.type === 'function') | |
| 690 object.callFunctionJSON( | |
| 691 getCompletions, [WebInspector.RemoteObject.toCallArgument(object.s
ubtype)], | |
| 692 receivedPropertyNames.bind(this)); | |
| 693 else if (object.type === 'string' || object.type === 'number' || object.
type === 'boolean') | |
| 694 this.evaluate( | |
| 695 '(' + getCompletions + ')("' + result.type + '")', 'completion', f
alse, true, true, false, false, | |
| 696 receivedPropertyNamesFromEval.bind(this)); | |
| 697 } | |
| 698 | |
| 699 extractTarget(result).then(completionsForObject.bind(this)); | |
| 700 } | |
| 701 | |
| 702 /** | |
| 703 * @param {?WebInspector.RemoteObject} result | |
| 704 * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails | |
| 705 * @this {WebInspector.ExecutionContext} | |
| 706 */ | |
| 707 function receivedPropertyNamesFromEval(result, exceptionDetails) { | |
| 708 this.target().runtimeAgent().releaseObjectGroup('completion'); | |
| 709 if (result && !exceptionDetails) | |
| 710 receivedPropertyNames.call(this, /** @type {!Object} */ (result.value)); | |
| 711 else | |
| 712 fufill([]); | |
| 713 } | |
| 714 | |
| 715 /** | |
| 716 * @param {?Object} propertyNames | |
| 717 * @this {WebInspector.ExecutionContext} | |
| 718 */ | |
| 719 function receivedPropertyNames(propertyNames) { | |
| 720 this.target().runtimeAgent().releaseObjectGroup('completion'); | |
| 721 if (!propertyNames) { | |
| 722 fufill([]); | |
| 723 return; | |
| 724 } | |
| 725 var includeCommandLineAPI = (!dotNotation && !bracketNotation); | |
| 726 if (includeCommandLineAPI) { | |
| 727 const commandLineAPI = [ | |
| 728 'dir', | |
| 729 'dirxml', | |
| 730 'keys', | |
| 731 'values', | |
| 732 'profile', | |
| 733 'profileEnd', | |
| 734 'monitorEvents', | |
| 735 'unmonitorEvents', | |
| 736 'inspect', | |
| 737 'copy', | |
| 738 'clear', | |
| 739 'getEventListeners', | |
| 740 'debug', | |
| 741 'undebug', | |
| 742 'monitor', | |
| 743 'unmonitor', | |
| 744 'table', | |
| 745 '$', | |
| 746 '$$', | |
| 747 '$x' | |
| 748 ]; | |
| 749 for (var i = 0; i < commandLineAPI.length; ++i) | |
| 750 propertyNames[commandLineAPI[i]] = true; | |
| 751 } | |
| 752 fufill(this._completionsForPrefix( | |
| 753 dotNotation, bracketNotation, expressionString, prefix, Object.keys(pr
opertyNames))); | |
| 754 } | |
| 755 } | |
| 756 | |
| 757 /** | |
| 758 * @param {boolean} dotNotation | |
| 759 * @param {boolean} bracketNotation | |
| 760 * @param {string} expressionString | |
| 761 * @param {string} prefix | |
| 762 * @param {!Array.<string>} properties | |
| 763 * @return {!Array<string>} | |
| 764 */ | |
| 765 _completionsForPrefix(dotNotation, bracketNotation, expressionString, prefix,
properties) { | |
| 766 if (bracketNotation) { | |
| 767 if (prefix.length && prefix[0] === '\'') | |
| 768 var quoteUsed = '\''; | |
| 769 else | |
| 770 var quoteUsed = '"'; | |
| 771 } | |
| 772 | |
| 773 var results = []; | |
| 774 | |
| 775 if (!expressionString) { | |
| 776 const keywords = [ | |
| 777 'break', 'case', 'catch', 'continue', 'default', 'delete', 'do',
'else', 'finally', | |
| 778 'for', 'function', 'if', 'in', 'instanceof', 'new', 'retu
rn', 'switch', 'this', | |
| 779 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with
' | |
| 780 ]; | |
| 781 properties = properties.concat(keywords); | |
| 782 } | |
| 783 | |
| 784 properties.sort(); | |
| 785 | |
| 786 for (var i = 0; i < properties.length; ++i) { | |
| 787 var property = properties[i]; | |
| 788 | |
| 789 // Assume that all non-ASCII characters are letters and thus can be used a
s part of identifier. | |
| 790 if (dotNotation && !/^[a-zA-Z_$\u008F-\uFFFF][a-zA-Z0-9_$\u008F-\uFFFF]*$/
.test(property)) | |
| 791 continue; | |
| 792 | |
| 793 if (bracketNotation) { | |
| 794 if (!/^[0-9]+$/.test(property)) | |
| 795 property = quoteUsed + property.escapeCharacters(quoteUsed + '\\') + q
uoteUsed; | |
| 796 property += ']'; | |
| 797 } | |
| 798 | |
| 799 if (property.length < prefix.length) | |
| 800 continue; | |
| 801 if (prefix.length && !property.startsWith(prefix)) | |
| 802 continue; | |
| 803 | |
| 804 // Substitute actual newlines with newline characters. @see crbug.com/4984
21 | |
| 805 results.push(property.split('\n').join('\\n')); | |
| 806 } | |
| 807 return results; | |
| 808 } | |
| 809 | |
| 810 /** | |
| 811 * @return {string} | 584 * @return {string} |
| 812 */ | 585 */ |
| 813 label() { | 586 label() { |
| 814 return this._label; | 587 return this._label; |
| 815 } | 588 } |
| 816 | 589 |
| 817 /** | 590 /** |
| 818 * @param {string} label | 591 * @param {string} label |
| 819 */ | 592 */ |
| 820 setLabel(label) { | 593 setLabel(label) { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 this._type === 'wheel'; | 783 this._type === 'wheel'; |
| 1011 } | 784 } |
| 1012 | 785 |
| 1013 /** | 786 /** |
| 1014 * @return {boolean} | 787 * @return {boolean} |
| 1015 */ | 788 */ |
| 1016 isNormalListenerType() { | 789 isNormalListenerType() { |
| 1017 return this._listenerType === 'normal'; | 790 return this._listenerType === 'normal'; |
| 1018 } | 791 } |
| 1019 }; | 792 }; |
| OLD | NEW |