mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-03 02:21:05 +08:00
All of the existing callsites passed only a callback parameter, with no additional `args` parameters, and so this functionality is equivalent to the built-in queueMicrotask(). Note that there are some upstream tests that currently still use setImmediate. These tests are ported in [1], which should be merged before this patch can land. [1]: https://chromium-review.googlesource.com/c/chromium/src/+/2563476 Bug: chromium:1050549 Change-Id: Iee3d286d38bcb17d9b78ca89f9897e8ca37b6d94 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2554560 Commit-Queue: Mathias Bynens <mathias@chromium.org> Reviewed-by: Mathias Bynens <mathias@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org>
258 lines
7.2 KiB
JavaScript
258 lines
7.2 KiB
JavaScript
// Copyright 2018 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.
|
|
|
|
import * as Common from '../common/common.js';
|
|
import * as SDK from '../sdk/sdk.js'; // eslint-disable-line no-unused-vars
|
|
import * as Search from '../search/search.js'; // eslint-disable-line no-unused-vars
|
|
import * as TextUtils from '../text_utils/text_utils.js'; // eslint-disable-line no-unused-vars
|
|
|
|
/**
|
|
* @implements {Search.SearchConfig.SearchScope}
|
|
*/
|
|
export class NetworkSearchScope {
|
|
/**
|
|
* @override
|
|
* @param {!Common.Progress.Progress} progress
|
|
*/
|
|
performIndexing(progress) {
|
|
queueMicrotask(() => {
|
|
progress.done();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!Search.SearchConfig.SearchConfig} searchConfig
|
|
* @param {!Common.Progress.Progress} progress
|
|
* @param {function(!Search.SearchConfig.SearchResult):void} searchResultCallback
|
|
* @param {function(boolean):void} searchFinishedCallback
|
|
* @return {!Promise<void>}
|
|
*/
|
|
async performSearch(searchConfig, progress, searchResultCallback, searchFinishedCallback) {
|
|
const promises = [];
|
|
const requests = SDK.NetworkLog.NetworkLog.instance().requests().filter(
|
|
request => searchConfig.filePathMatchesFileQuery(request.url()));
|
|
progress.setTotalWork(requests.length);
|
|
for (const request of requests) {
|
|
const promise = this._searchRequest(searchConfig, request, progress);
|
|
promises.push(promise);
|
|
}
|
|
const resultsWithNull = await Promise.all(promises);
|
|
const results = /** @type {!Array<!NetworkSearchResult>} */ (resultsWithNull.filter(result => result !== null));
|
|
if (progress.isCanceled()) {
|
|
searchFinishedCallback(false);
|
|
return;
|
|
}
|
|
for (const result of results.sort((r1, r2) => r1.label().localeCompare(r2.label()))) {
|
|
if (result.matchesCount() > 0) {
|
|
searchResultCallback(result);
|
|
}
|
|
}
|
|
progress.done();
|
|
searchFinishedCallback(true);
|
|
}
|
|
|
|
/**
|
|
* @param {!Search.SearchConfig.SearchConfig} searchConfig
|
|
* @param {!SDK.NetworkRequest.NetworkRequest} request
|
|
* @param {!Common.Progress.Progress} progress
|
|
* @return {!Promise<?NetworkSearchResult>}
|
|
*/
|
|
async _searchRequest(searchConfig, request, progress) {
|
|
/** @type {!Array<!TextUtils.ContentProvider.SearchMatch>} */
|
|
let bodyMatches = [];
|
|
if (request.contentType().isTextType()) {
|
|
bodyMatches =
|
|
await request.searchInContent(searchConfig.query(), !searchConfig.ignoreCase(), searchConfig.isRegex());
|
|
}
|
|
if (progress.isCanceled()) {
|
|
return null;
|
|
}
|
|
const locations = [];
|
|
if (stringMatchesQuery(request.url())) {
|
|
locations.push(UIRequestLocation.urlMatch(request));
|
|
}
|
|
for (const header of request.requestHeaders()) {
|
|
if (headerMatchesQuery(header)) {
|
|
locations.push(UIRequestLocation.requestHeaderMatch(request, header));
|
|
}
|
|
}
|
|
for (const header of request.responseHeaders) {
|
|
if (headerMatchesQuery(header)) {
|
|
locations.push(UIRequestLocation.responseHeaderMatch(request, header));
|
|
}
|
|
}
|
|
for (const match of bodyMatches) {
|
|
locations.push(UIRequestLocation.bodyMatch(request, match));
|
|
}
|
|
progress.worked();
|
|
return new NetworkSearchResult(request, locations);
|
|
|
|
/**
|
|
* @param {!SDK.NetworkRequest.NameValue} header
|
|
* @return {boolean}
|
|
*/
|
|
function headerMatchesQuery(header) {
|
|
return stringMatchesQuery(`${header.name}: ${header.value}`);
|
|
}
|
|
|
|
/**
|
|
* @param {string} string
|
|
* @return {boolean}
|
|
*/
|
|
function stringMatchesQuery(string) {
|
|
const flags = searchConfig.ignoreCase() ? 'i' : '';
|
|
const regExps = searchConfig.queries().map(query => new RegExp(query, flags));
|
|
let pos = 0;
|
|
for (const regExp of regExps) {
|
|
const match = string.substr(pos).match(regExp);
|
|
if (!match || !match.index) {
|
|
return false;
|
|
}
|
|
pos += match.index + match[0].length;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
stopSearch() {
|
|
}
|
|
}
|
|
|
|
export class UIRequestLocation {
|
|
/**
|
|
* @param {!SDK.NetworkRequest.NetworkRequest} request
|
|
* @param {?SDK.NetworkRequest.NameValue} requestHeader
|
|
* @param {?SDK.NetworkRequest.NameValue} responseHeader
|
|
* @param {?TextUtils.ContentProvider.SearchMatch} searchMatch
|
|
* @param {boolean} urlMatch
|
|
*/
|
|
constructor(request, requestHeader, responseHeader, searchMatch, urlMatch) {
|
|
this.request = request;
|
|
this.requestHeader = requestHeader;
|
|
this.responseHeader = responseHeader;
|
|
this.searchMatch = searchMatch;
|
|
this.isUrlMatch = urlMatch;
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.NetworkRequest.NetworkRequest} request
|
|
* @param {?SDK.NetworkRequest.NameValue} header
|
|
*/
|
|
static requestHeaderMatch(request, header) {
|
|
return new UIRequestLocation(request, header, null, null, false);
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.NetworkRequest.NetworkRequest} request
|
|
* @param {?SDK.NetworkRequest.NameValue} header
|
|
*/
|
|
static responseHeaderMatch(request, header) {
|
|
return new UIRequestLocation(request, null, header, null, false);
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.NetworkRequest.NetworkRequest} request
|
|
* @param {?TextUtils.ContentProvider.SearchMatch} searchMatch
|
|
*/
|
|
static bodyMatch(request, searchMatch) {
|
|
return new UIRequestLocation(request, null, null, searchMatch, false);
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.NetworkRequest.NetworkRequest} request
|
|
*/
|
|
static urlMatch(request) {
|
|
return new UIRequestLocation(request, null, null, null, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @implements Search.SearchConfig.SearchResult
|
|
*/
|
|
export class NetworkSearchResult {
|
|
/**
|
|
* @param {!SDK.NetworkRequest.NetworkRequest} request
|
|
* @param {!Array<!UIRequestLocation>} locations
|
|
*/
|
|
constructor(request, locations) {
|
|
this._request = request;
|
|
this._locations = locations;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {number}
|
|
*/
|
|
matchesCount() {
|
|
return this._locations.length;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {string}
|
|
*/
|
|
label() {
|
|
return this._request.displayName;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {string}
|
|
*/
|
|
description() {
|
|
const parsedUrl = this._request.parsedURL;
|
|
if (!parsedUrl) {
|
|
return this._request.url();
|
|
}
|
|
return parsedUrl.urlWithoutScheme();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {number} index
|
|
* @return {string}
|
|
*/
|
|
matchLineContent(index) {
|
|
const location = this._locations[index];
|
|
if (location.isUrlMatch) {
|
|
return this._request.url();
|
|
}
|
|
const header = location.requestHeader || location.responseHeader;
|
|
if (header) {
|
|
return header.value;
|
|
}
|
|
return /** @type {!TextUtils.ContentProvider.SearchMatch} */ (location.searchMatch).lineContent;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {number} index
|
|
* @return {!Object}
|
|
*/
|
|
matchRevealable(index) {
|
|
return this._locations[index];
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {number} index
|
|
* @return {?}
|
|
*/
|
|
matchLabel(index) {
|
|
const location = this._locations[index];
|
|
if (location.isUrlMatch) {
|
|
return Common.UIString.UIString('URL');
|
|
}
|
|
const header = location.requestHeader || location.responseHeader;
|
|
if (header) {
|
|
return `${header.name}:`;
|
|
}
|
|
return /** @type {!TextUtils.ContentProvider.SearchMatch} */ (location.searchMatch).lineNumber + 1;
|
|
}
|
|
}
|