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

Unified Diff: third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js

Issue 2712513002: DevTools: extract ObjectUI module from Components (Closed)
Patch Set: fix build.gn Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js
diff --git a/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js b/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js
deleted file mode 100644
index 8d6986454bc5fb3e7ffce9e5ba04049a58908a97..0000000000000000000000000000000000000000
--- a/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js
+++ /dev/null
@@ -1,469 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-Components.JavaScriptAutocomplete = {};
-
-/** @typedef {{title:(string|undefined), items:Array<string>}} */
-Components.JavaScriptAutocomplete.CompletionGroup;
-
-/**
- * @param {string} text
- * @param {string} query
- * @param {boolean=} force
- * @return {!Promise<!UI.SuggestBox.Suggestions>}
- */
-Components.JavaScriptAutocomplete.completionsForTextInCurrentContext = function(text, query, force) {
- var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text, true);
- var mapCompletionsPromise = Components.JavaScriptAutocomplete._mapCompletions(text, query);
- return Components.JavaScriptAutocomplete.completionsForExpression(clippedExpression, query, force)
- .then(completions => mapCompletionsPromise.then(mapCompletions => mapCompletions.concat(completions)));
-};
-
-/**
- * @param {string} text
- * @param {boolean=} allowEndingBracket
- * @return {string}
- */
-Components.JavaScriptAutocomplete._clipExpression = function(text, allowEndingBracket) {
- var index;
- var stopChars = new Set('=:({;,!+-*/&|^<>`'.split(''));
- var whiteSpaceChars = new Set(' \r\n\t'.split(''));
- var continueChars = new Set('[. \r\n\t'.split(''));
-
- for (index = text.length - 1; index >= 0; index--) {
- if (stopChars.has(text.charAt(index)))
- break;
- if (whiteSpaceChars.has(text.charAt(index)) && !continueChars.has(text.charAt(index - 1)))
- break;
- }
- var clippedExpression = text.substring(index + 1).trim();
- var bracketCount = 0;
-
- index = clippedExpression.length - 1;
- while (index >= 0) {
- var character = clippedExpression.charAt(index);
- if (character === ']')
- bracketCount++;
- // Allow an open bracket at the end for property completion.
- if (character === '[' && (index < clippedExpression.length - 1 || !allowEndingBracket)) {
- bracketCount--;
- if (bracketCount < 0)
- break;
- }
- index--;
- }
- return clippedExpression.substring(index + 1).trim();
-};
-
-/**
- * @param {string} text
- * @param {string} query
- * @return {!Promise<!UI.SuggestBox.Suggestions>}
- */
-Components.JavaScriptAutocomplete._mapCompletions = function(text, query) {
- var mapMatch = text.match(/\.\s*(get|set|delete)\s*\(\s*$/);
- var executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext || !mapMatch)
- return Promise.resolve([]);
-
- var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text.substring(0, mapMatch.index));
- var fulfill;
- var promise = new Promise(x => fulfill = x);
- executionContext.evaluate(clippedExpression, 'completion', true, true, false, false, false, evaluated);
- return promise;
-
- /**
- * @param {?SDK.RemoteObject} result
- * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
- */
- function evaluated(result, exceptionDetails) {
- if (!result || !!exceptionDetails || result.subtype !== 'map') {
- fulfill([]);
- return;
- }
- result.getOwnPropertiesPromise(false).then(extractEntriesProperty);
- }
-
- /**
- * @param {!{properties: ?Array<!SDK.RemoteObjectProperty>, internalProperties: ?Array<!SDK.RemoteObjectProperty>}} properties
- */
- function extractEntriesProperty(properties) {
- var internalProperties = properties.internalProperties || [];
- var entriesProperty = internalProperties.find(property => property.name === '[[Entries]]');
- if (!entriesProperty) {
- fulfill([]);
- return;
- }
- entriesProperty.value.callFunctionJSONPromise(getEntries).then(keysObj => gotKeys(Object.keys(keysObj)));
- }
-
- /**
- * @suppressReceiverCheck
- * @this {!Array<{key:?, value:?}>}
- * @return {!Object}
- */
- function getEntries() {
- var result = {__proto__: null};
- for (var i = 0; i < this.length; i++) {
- if (typeof this[i].key === 'string')
- result[this[i].key] = true;
- }
- return result;
- }
-
- /**
- * @param {!Array<string>} rawKeys
- */
- function gotKeys(rawKeys) {
- var caseSensitivePrefix = [];
- var caseInsensitivePrefix = [];
- var caseSensitiveAnywhere = [];
- var caseInsensitiveAnywhere = [];
- var quoteChar = '"';
- if (query.startsWith('\''))
- quoteChar = '\'';
- var endChar = ')';
- if (mapMatch[0].indexOf('set') !== -1)
- endChar = ', ';
-
- var sorter = rawKeys.length < 1000 ? String.naturalOrderComparator : undefined;
- var keys = rawKeys.sort(sorter).map(key => quoteChar + key + quoteChar);
-
- for (var key of keys) {
- if (key.length < query.length)
- continue;
- if (query.length && key.toLowerCase().indexOf(query.toLowerCase()) === -1)
- continue;
- // Substitute actual newlines with newline characters. @see crbug.com/498421
- var title = key.split('\n').join('\\n');
- var text = title + endChar;
-
- if (key.startsWith(query))
- caseSensitivePrefix.push({text: text, title: title, priority: 4});
- else if (key.toLowerCase().startsWith(query.toLowerCase()))
- caseInsensitivePrefix.push({text: text, title: title, priority: 3});
- else if (key.indexOf(query) !== -1)
- caseSensitiveAnywhere.push({text: text, title: title, priority: 2});
- else
- caseInsensitiveAnywhere.push({text: text, title: title, priority: 1});
- }
- var suggestions = caseSensitivePrefix.concat(caseInsensitivePrefix, caseSensitiveAnywhere, caseInsensitiveAnywhere);
- if (suggestions.length)
- suggestions[0].subtitle = Common.UIString('Keys');
- fulfill(suggestions);
- }
-};
-
-/**
- * @param {string} expressionString
- * @param {string} query
- * @param {boolean=} force
- * @return {!Promise<!UI.SuggestBox.Suggestions>}
- */
-Components.JavaScriptAutocomplete.completionsForExpression = function(expressionString, query, force) {
- var executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext)
- return Promise.resolve([]);
-
- var lastIndex = expressionString.length - 1;
-
- var dotNotation = (expressionString[lastIndex] === '.');
- var bracketNotation = (expressionString.length > 1 && expressionString[lastIndex] === '[');
-
- if (dotNotation || bracketNotation)
- expressionString = expressionString.substr(0, lastIndex);
- else
- expressionString = '';
-
- // User is entering float value, do not suggest anything.
- if ((expressionString && !isNaN(expressionString)) || (!expressionString && query && !isNaN(query)))
- return Promise.resolve([]);
-
-
- if (!query && !expressionString && !force)
- return Promise.resolve([]);
-
- var fulfill;
- var promise = new Promise(x => fulfill = x);
- var selectedFrame = executionContext.debuggerModel.selectedCallFrame();
- if (!expressionString && selectedFrame)
- variableNamesInScopes(selectedFrame, receivedPropertyNames);
- else
- executionContext.evaluate(expressionString, 'completion', true, true, false, false, false, evaluated);
-
- return promise;
- /**
- * @param {?SDK.RemoteObject} result
- * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
- */
- function evaluated(result, exceptionDetails) {
- if (!result || !!exceptionDetails) {
- fulfill([]);
- return;
- }
-
- /**
- * @param {?SDK.RemoteObject} object
- * @return {!Promise<?SDK.RemoteObject>}
- */
- function extractTarget(object) {
- if (!object)
- return Promise.resolve(/** @type {?SDK.RemoteObject} */ (null));
- if (object.type !== 'object' || object.subtype !== 'proxy')
- return Promise.resolve(/** @type {?SDK.RemoteObject} */ (object));
- return object.getOwnPropertiesPromise(false /* generatePreview */)
- .then(extractTargetFromProperties)
- .then(extractTarget);
- }
-
- /**
- * @param {!{properties: ?Array<!SDK.RemoteObjectProperty>, internalProperties: ?Array<!SDK.RemoteObjectProperty>}} properties
- * @return {?SDK.RemoteObject}
- */
- function extractTargetFromProperties(properties) {
- var internalProperties = properties.internalProperties || [];
- var target = internalProperties.find(property => property.name === '[[Target]]');
- return target ? target.value : null;
- }
-
- /**
- * @param {string=} type
- * @return {!Object}
- * @suppressReceiverCheck
- * @this {Object}
- */
- function getCompletions(type) {
- var object;
- if (type === 'string')
- object = new String('');
- else if (type === 'number')
- object = new Number(0);
- else if (type === 'boolean')
- object = new Boolean(false);
- else
- object = this;
-
- var result = [];
- try {
- for (var o = object; o; o = Object.getPrototypeOf(o)) {
- if ((type === 'array' || type === 'typedarray') && o === object && ArrayBuffer.isView(o) && o.length > 9999)
- continue;
-
- var group = {items: [], __proto__: null};
- try {
- if (typeof o === 'object' && o.constructor && o.constructor.name)
- group.title = o.constructor.name;
- } catch (ee) {
- // we could break upon cross origin check.
- }
- result[result.length] = group;
- var names = Object.getOwnPropertyNames(o);
- var isArray = Array.isArray(o);
- for (var i = 0; i < names.length; ++i) {
- // Skip array elements indexes.
- if (isArray && /^[0-9]/.test(names[i]))
- continue;
- group.items[group.items.length] = names[i];
- }
- }
- } catch (e) {
- }
- return result;
- }
-
- /**
- * @param {?SDK.RemoteObject} object
- */
- function completionsForObject(object) {
- if (!object) {
- receivedPropertyNames(null);
- } else if (object.type === 'object' || object.type === 'function') {
- object.callFunctionJSON(
- getCompletions, [SDK.RemoteObject.toCallArgument(object.subtype)], receivedPropertyNames);
- } else if (object.type === 'string' || object.type === 'number' || object.type === 'boolean') {
- executionContext.evaluate(
- '(' + getCompletions + ')("' + result.type + '")', 'completion', false, true, true, false, false,
- receivedPropertyNamesFromEval);
- }
- }
-
- extractTarget(result).then(completionsForObject);
- }
-
- /**
- * @param {!SDK.DebuggerModel.CallFrame} callFrame
- * @param {function(!Array<!Components.JavaScriptAutocomplete.CompletionGroup>)} callback
- */
- function variableNamesInScopes(callFrame, callback) {
- var result = [{items: ['this']}];
-
- /**
- * @param {string} name
- * @param {?Array<!SDK.RemoteObjectProperty>} properties
- */
- function propertiesCollected(name, properties) {
- var group = {title: name, items: []};
- result.push(group);
- for (var i = 0; properties && i < properties.length; ++i)
- group.items.push(properties[i].name);
- if (--pendingRequests === 0)
- callback(result);
- }
-
- var scopeChain = callFrame.scopeChain();
- var pendingRequests = scopeChain.length;
- for (var i = 0; i < scopeChain.length; ++i) {
- var scope = scopeChain[i];
- var object = scope.object();
- object.getAllProperties(
- false /* accessorPropertiesOnly */, false /* generatePreview */,
- propertiesCollected.bind(null, scope.typeName()));
- }
- }
-
- /**
- * @param {?SDK.RemoteObject} result
- * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
- */
- function receivedPropertyNamesFromEval(result, exceptionDetails) {
- executionContext.target().runtimeAgent().releaseObjectGroup('completion');
- if (result && !exceptionDetails)
- receivedPropertyNames(/** @type {!Object} */ (result.value));
- else
- fulfill([]);
- }
-
- /**
- * @param {?Object} object
- */
- function receivedPropertyNames(object) {
- executionContext.target().runtimeAgent().releaseObjectGroup('completion');
- if (!object) {
- fulfill([]);
- return;
- }
- var propertyGroups = /** @type {!Array<!Components.JavaScriptAutocomplete.CompletionGroup>} */ (object);
- var includeCommandLineAPI = (!dotNotation && !bracketNotation);
- if (includeCommandLineAPI) {
- const commandLineAPI = [
- 'dir',
- 'dirxml',
- 'keys',
- 'values',
- 'profile',
- 'profileEnd',
- 'monitorEvents',
- 'unmonitorEvents',
- 'inspect',
- 'copy',
- 'clear',
- 'getEventListeners',
- 'debug',
- 'undebug',
- 'monitor',
- 'unmonitor',
- 'table',
- '$',
- '$$',
- '$x'
- ];
- propertyGroups.push({items: commandLineAPI});
- }
- fulfill(Components.JavaScriptAutocomplete._completionsForQuery(
- dotNotation, bracketNotation, expressionString, query, propertyGroups));
- }
-};
-
-/**
- * @param {boolean} dotNotation
- * @param {boolean} bracketNotation
- * @param {string} expressionString
- * @param {string} query
- * @param {!Array<!Components.JavaScriptAutocomplete.CompletionGroup>} propertyGroups
- * @return {!UI.SuggestBox.Suggestions}
- */
-Components.JavaScriptAutocomplete._completionsForQuery = function(
- dotNotation, bracketNotation, expressionString, query, propertyGroups) {
- if (bracketNotation) {
- if (query.length && query[0] === '\'')
- var quoteUsed = '\'';
- else
- var quoteUsed = '"';
- }
-
- if (!expressionString) {
- const keywords = [
- 'break', 'case', 'catch', 'continue', 'default', 'delete', 'do', 'else', 'finally',
- 'for', 'function', 'if', 'in', 'instanceof', 'new', 'return', 'switch', 'this',
- 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with'
- ];
- propertyGroups.push({title: Common.UIString('keywords'), items: keywords});
- }
-
- var result = [];
- var lastGroupTitle;
- for (var group of propertyGroups) {
- group.items.sort(itemComparator.bind(null, group.items.length > 1000));
- var caseSensitivePrefix = [];
- var caseInsensitivePrefix = [];
- var caseSensitiveAnywhere = [];
- var caseInsensitiveAnywhere = [];
-
- for (var property of group.items) {
- // Assume that all non-ASCII characters are letters and thus can be used as part of identifier.
- if (!bracketNotation && !/^[a-zA-Z_$\u008F-\uFFFF][a-zA-Z0-9_$\u008F-\uFFFF]*$/.test(property))
- continue;
-
- if (bracketNotation) {
- if (!/^[0-9]+$/.test(property))
- property = quoteUsed + property.escapeCharacters(quoteUsed + '\\') + quoteUsed;
- property += ']';
- }
-
- if (property.length < query.length)
- continue;
- if (query.length && property.toLowerCase().indexOf(query.toLowerCase()) === -1)
- continue;
- // Substitute actual newlines with newline characters. @see crbug.com/498421
- var prop = property.split('\n').join('\\n');
-
- if (property.startsWith(query))
- caseSensitivePrefix.push({text: prop, priority: 4});
- else if (property.toLowerCase().startsWith(query.toLowerCase()))
- caseInsensitivePrefix.push({text: prop, priority: 3});
- else if (property.indexOf(query) !== -1)
- caseSensitiveAnywhere.push({text: prop, priority: 2});
- else
- caseInsensitiveAnywhere.push({text: prop, priority: 1});
- }
- var structuredGroup =
- caseSensitivePrefix.concat(caseInsensitivePrefix, caseSensitiveAnywhere, caseInsensitiveAnywhere);
- if (structuredGroup.length && group.title !== lastGroupTitle) {
- structuredGroup[0].subtitle = group.title;
- lastGroupTitle = group.title;
- }
- result = result.concat(structuredGroup);
- result.forEach(item => {
- if (item.text.endsWith(']'))
- item.title = item.text.substring(0, item.text.length - 1);
- });
- }
- return result;
-
- /**
- * @param {boolean} naturalOrder
- * @param {string} a
- * @param {string} b
- * @return {number}
- */
- function itemComparator(naturalOrder, a, b) {
- var aStartsWithUnderscore = a.startsWith('_');
- var bStartsWithUnderscore = b.startsWith('_');
- if (aStartsWithUnderscore && !bStartsWithUnderscore)
- return 1;
- if (bStartsWithUnderscore && !aStartsWithUnderscore)
- return -1;
- return naturalOrder ? String.naturalOrderComparator(a, b) : a.localeCompare(b);
- }
-};

Powered by Google App Engine
This is Rietveld 408576698