chrome-devtools-frontend 1.0.1004171 → 1.0.1004641
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/gni/devtools_grd_files.gni +2 -0
- package/front_end/core/common/ParsedURL.ts +3 -3
- package/front_end/core/i18n/locales/en-US.json +39 -0
- package/front_end/core/i18n/locales/en-XL.json +39 -0
- package/front_end/core/sdk/DebuggerModel.ts +12 -0
- package/front_end/core/sdk/RuntimeModel.ts +5 -3
- package/front_end/models/extensions/ExtensionPanel.ts +1 -1
- package/front_end/models/extensions/ExtensionServer.ts +11 -10
- package/front_end/models/har/Log.ts +4 -3
- package/front_end/panels/network/NetworkItemView.ts +10 -1
- package/front_end/panels/network/RequestHeadersView.ts +1 -1
- package/front_end/panels/network/components/RequestHeadersView.css +78 -0
- package/front_end/panels/network/components/RequestHeadersView.ts +262 -0
- package/front_end/panels/network/components/components.ts +2 -0
- package/front_end/panels/network/forward/UIRequestLocation.ts +1 -0
- package/front_end/panels/network/networkLogView.css +3 -3
- package/front_end/panels/network/requestHeadersTree.css +6 -0
- package/front_end/panels/sources/CallStackSidebarPane.ts +13 -0
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +4 -3
- package/front_end/panels/sources/sourcesView.css +4 -0
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +16 -2
- package/front_end/ui/legacy/components/data_grid/ViewportDataGrid.ts +2 -2
- package/package.json +1 -1
@@ -1112,6 +1112,8 @@ grd_files_debug_sources = [
|
|
1112
1112
|
"front_end/panels/network/SignedExchangeInfoView.js",
|
1113
1113
|
"front_end/panels/network/binaryResourceView.css.js",
|
1114
1114
|
"front_end/panels/network/blockedURLsPane.css.js",
|
1115
|
+
"front_end/panels/network/components/RequestHeadersView.css.js",
|
1116
|
+
"front_end/panels/network/components/RequestHeadersView.js",
|
1115
1117
|
"front_end/panels/network/components/RequestTrustTokensView.css.js",
|
1116
1118
|
"front_end/panels/network/components/RequestTrustTokensView.js",
|
1117
1119
|
"front_end/panels/network/components/WebBundleInfoView.css.js",
|
@@ -264,9 +264,9 @@ export class ParsedURL {
|
|
264
264
|
return devToolsPaths.join(separator) as DevToolsPathType;
|
265
265
|
}
|
266
266
|
|
267
|
-
static split<DevToolsPathType extends BrandedPathString>(
|
268
|
-
DevToolsPathType[] {
|
269
|
-
return devToolsPath.split(separator) as DevToolsPathType[];
|
267
|
+
static split<DevToolsPathType extends BrandedPathString>(
|
268
|
+
devToolsPath: DevToolsPathType, separator: string|RegExp, limit?: number): DevToolsPathType[] {
|
269
|
+
return devToolsPath.split(separator, limit) as DevToolsPathType[];
|
270
270
|
}
|
271
271
|
|
272
272
|
static toLowerCase<DevToolsPathType extends BrandedPathString>(devToolsPath: DevToolsPathType): DevToolsPathType {
|
@@ -6599,6 +6599,42 @@
|
|
6599
6599
|
"panels/network/BlockedURLsPane.ts | textPatternToBlockMatching": {
|
6600
6600
|
"message": "Text pattern to block matching requests; use * for wildcard"
|
6601
6601
|
},
|
6602
|
+
"panels/network/components/RequestHeadersView.ts | fromDiskCache": {
|
6603
|
+
"message": "(from disk cache)"
|
6604
|
+
},
|
6605
|
+
"panels/network/components/RequestHeadersView.ts | fromMemoryCache": {
|
6606
|
+
"message": "(from memory cache)"
|
6607
|
+
},
|
6608
|
+
"panels/network/components/RequestHeadersView.ts | fromPrefetchCache": {
|
6609
|
+
"message": "(from prefetch cache)"
|
6610
|
+
},
|
6611
|
+
"panels/network/components/RequestHeadersView.ts | fromServiceWorker": {
|
6612
|
+
"message": "(from service worker)"
|
6613
|
+
},
|
6614
|
+
"panels/network/components/RequestHeadersView.ts | fromSignedexchange": {
|
6615
|
+
"message": "(from signed-exchange)"
|
6616
|
+
},
|
6617
|
+
"panels/network/components/RequestHeadersView.ts | fromWebBundle": {
|
6618
|
+
"message": "(from Web Bundle)"
|
6619
|
+
},
|
6620
|
+
"panels/network/components/RequestHeadersView.ts | general": {
|
6621
|
+
"message": "General"
|
6622
|
+
},
|
6623
|
+
"panels/network/components/RequestHeadersView.ts | referrerPolicy": {
|
6624
|
+
"message": "Referrer Policy"
|
6625
|
+
},
|
6626
|
+
"panels/network/components/RequestHeadersView.ts | remoteAddress": {
|
6627
|
+
"message": "Remote Address"
|
6628
|
+
},
|
6629
|
+
"panels/network/components/RequestHeadersView.ts | requestMethod": {
|
6630
|
+
"message": "Request Method"
|
6631
|
+
},
|
6632
|
+
"panels/network/components/RequestHeadersView.ts | requestUrl": {
|
6633
|
+
"message": "Request URL"
|
6634
|
+
},
|
6635
|
+
"panels/network/components/RequestHeadersView.ts | statusCode": {
|
6636
|
+
"message": "Status Code"
|
6637
|
+
},
|
6602
6638
|
"panels/network/components/RequestTrustTokensView.ts | aClientprovidedArgumentWas": {
|
6603
6639
|
"message": "A client-provided argument was malformed or otherwise invalid."
|
6604
6640
|
},
|
@@ -9461,6 +9497,9 @@
|
|
9461
9497
|
"panels/sources/CallStackSidebarPane.ts | removeFromIgnoreList": {
|
9462
9498
|
"message": "Remove from ignore list"
|
9463
9499
|
},
|
9500
|
+
"panels/sources/CallStackSidebarPane.ts | restartFrame": {
|
9501
|
+
"message": "Restart frame"
|
9502
|
+
},
|
9464
9503
|
"panels/sources/CallStackSidebarPane.ts | showIgnorelistedFrames": {
|
9465
9504
|
"message": "Show ignore-listed frames"
|
9466
9505
|
},
|
@@ -6599,6 +6599,42 @@
|
|
6599
6599
|
"panels/network/BlockedURLsPane.ts | textPatternToBlockMatching": {
|
6600
6600
|
"message": "T̂éx̂t́ p̂át̂t́êŕn̂ t́ô b́l̂óĉḱ m̂át̂ćĥín̂ǵ r̂éq̂úêśt̂ś; ûśê * f́ôŕ ŵíl̂d́ĉár̂d́"
|
6601
6601
|
},
|
6602
|
+
"panels/network/components/RequestHeadersView.ts | fromDiskCache": {
|
6603
|
+
"message": "(f̂ŕôḿ d̂íŝḱ ĉáĉh́ê)"
|
6604
|
+
},
|
6605
|
+
"panels/network/components/RequestHeadersView.ts | fromMemoryCache": {
|
6606
|
+
"message": "(f̂ŕôḿ m̂ém̂ór̂ý ĉáĉh́ê)"
|
6607
|
+
},
|
6608
|
+
"panels/network/components/RequestHeadersView.ts | fromPrefetchCache": {
|
6609
|
+
"message": "(f̂ŕôḿ p̂ŕêf́êt́ĉh́ ĉáĉh́ê)"
|
6610
|
+
},
|
6611
|
+
"panels/network/components/RequestHeadersView.ts | fromServiceWorker": {
|
6612
|
+
"message": "(f̂ŕôḿ service worker)"
|
6613
|
+
},
|
6614
|
+
"panels/network/components/RequestHeadersView.ts | fromSignedexchange": {
|
6615
|
+
"message": "(f̂ŕôḿ ŝíĝńêd́-êx́ĉh́âńĝé)"
|
6616
|
+
},
|
6617
|
+
"panels/network/components/RequestHeadersView.ts | fromWebBundle": {
|
6618
|
+
"message": "(f̂ŕôḿ Ŵéb̂ B́ûńd̂ĺê)"
|
6619
|
+
},
|
6620
|
+
"panels/network/components/RequestHeadersView.ts | general": {
|
6621
|
+
"message": "Ĝén̂ér̂ál̂"
|
6622
|
+
},
|
6623
|
+
"panels/network/components/RequestHeadersView.ts | referrerPolicy": {
|
6624
|
+
"message": "R̂éf̂ér̂ŕêŕ P̂ól̂íĉý"
|
6625
|
+
},
|
6626
|
+
"panels/network/components/RequestHeadersView.ts | remoteAddress": {
|
6627
|
+
"message": "R̂ém̂ót̂é Âd́d̂ŕêśŝ"
|
6628
|
+
},
|
6629
|
+
"panels/network/components/RequestHeadersView.ts | requestMethod": {
|
6630
|
+
"message": "R̂éq̂úêśt̂ Ḿêt́ĥód̂"
|
6631
|
+
},
|
6632
|
+
"panels/network/components/RequestHeadersView.ts | requestUrl": {
|
6633
|
+
"message": "R̂éq̂úêśt̂ ÚR̂Ĺ"
|
6634
|
+
},
|
6635
|
+
"panels/network/components/RequestHeadersView.ts | statusCode": {
|
6636
|
+
"message": "Ŝt́ât́ûś Ĉód̂é"
|
6637
|
+
},
|
6602
6638
|
"panels/network/components/RequestTrustTokensView.ts | aClientprovidedArgumentWas": {
|
6603
6639
|
"message": "Â ćl̂íêńt̂-ṕr̂óv̂íd̂éd̂ ár̂ǵûḿêńt̂ ẃâś m̂ál̂f́ôŕm̂éd̂ ór̂ ót̂h́êŕŵíŝé îńv̂ál̂íd̂."
|
6604
6640
|
},
|
@@ -9461,6 +9497,9 @@
|
|
9461
9497
|
"panels/sources/CallStackSidebarPane.ts | removeFromIgnoreList": {
|
9462
9498
|
"message": "R̂ém̂óv̂é f̂ŕôḿ îǵn̂ór̂é l̂íŝt́"
|
9463
9499
|
},
|
9500
|
+
"panels/sources/CallStackSidebarPane.ts | restartFrame": {
|
9501
|
+
"message": "R̂éŝt́âŕt̂ f́r̂ám̂é"
|
9502
|
+
},
|
9464
9503
|
"panels/sources/CallStackSidebarPane.ts | showIgnorelistedFrames": {
|
9465
9504
|
"message": "Ŝh́ôẃ îǵn̂ór̂é-l̂íŝt́êd́ f̂ŕâḿêś"
|
9466
9505
|
},
|
@@ -1248,6 +1248,8 @@ export class CallFrame {
|
|
1248
1248
|
#returnValueInternal: RemoteObject|null;
|
1249
1249
|
readonly warnings: string[] = [];
|
1250
1250
|
|
1251
|
+
readonly canBeRestarted: boolean;
|
1252
|
+
|
1251
1253
|
constructor(
|
1252
1254
|
debuggerModel: DebuggerModel, script: Script, payload: Protocol.Debugger.CallFrame, inlineFrameIndex?: number,
|
1253
1255
|
functionName?: string) {
|
@@ -1259,6 +1261,7 @@ export class CallFrame {
|
|
1259
1261
|
this.#localScopeInternal = null;
|
1260
1262
|
this.#inlineFrameIndexInternal = inlineFrameIndex || 0;
|
1261
1263
|
this.#functionNameInternal = functionName || payload.functionName;
|
1264
|
+
this.canBeRestarted = Boolean(payload.canBeRestarted);
|
1262
1265
|
for (let i = 0; i < payload.scopeChain.length; ++i) {
|
1263
1266
|
const scope = new Scope(this, i);
|
1264
1267
|
this.#scopeChainInternal.push(scope);
|
@@ -1390,6 +1393,15 @@ export class CallFrame {
|
|
1390
1393
|
return {object: runtimeModel.createRemoteObject(response.result), exceptionDetails: response.exceptionDetails};
|
1391
1394
|
}
|
1392
1395
|
|
1396
|
+
async restart(): Promise<void> {
|
1397
|
+
console.assert(this.canBeRestarted, 'This frame can not be restarted.');
|
1398
|
+
// Note that even if `canBeRestarted` is true, the restart frame call can still fail.
|
1399
|
+
// The user can evaluate arbitrary code between pausing and restarting the frame that
|
1400
|
+
// could mess with the call stack.
|
1401
|
+
await this.debuggerModel.agent.invoke_restartFrame(
|
1402
|
+
{callFrameId: this.id, mode: Protocol.Debugger.RestartFrameRequestMode.StepInto});
|
1403
|
+
}
|
1404
|
+
|
1393
1405
|
getPayload(): Protocol.Debugger.CallFrame {
|
1394
1406
|
return this.payload;
|
1395
1407
|
}
|
@@ -36,6 +36,7 @@ import * as Common from '../common/common.js';
|
|
36
36
|
import * as Host from '../host/host.js';
|
37
37
|
import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
|
38
38
|
import type * as Protocol from '../../generated/protocol.js';
|
39
|
+
import type * as Platform from '../platform/platform.js';
|
39
40
|
|
40
41
|
import type {FunctionDetails} from './DebuggerModel.js';
|
41
42
|
import {DebuggerModel} from './DebuggerModel.js';
|
@@ -121,7 +122,8 @@ export class RuntimeModel extends SDKModel<EventTypes> {
|
|
121
122
|
executionContextCreated(context: Protocol.Runtime.ExecutionContextDescription): void {
|
122
123
|
const data = context.auxData || {isDefault: true};
|
123
124
|
const executionContext = new ExecutionContext(
|
124
|
-
this, context.id, context.uniqueId, context.name, context.origin
|
125
|
+
this, context.id, context.uniqueId, context.name, context.origin as Platform.DevToolsPath.UrlString,
|
126
|
+
data['isDefault'], data['frameId']);
|
125
127
|
this.#executionContextById.set(executionContext.id, executionContext);
|
126
128
|
this.dispatchEventToListeners(Events.ExecutionContextCreated, executionContext);
|
127
129
|
}
|
@@ -561,14 +563,14 @@ export class ExecutionContext {
|
|
561
563
|
uniqueId: string;
|
562
564
|
name: string;
|
563
565
|
#labelInternal: string|null;
|
564
|
-
origin:
|
566
|
+
origin: Platform.DevToolsPath.UrlString;
|
565
567
|
isDefault: boolean;
|
566
568
|
runtimeModel: RuntimeModel;
|
567
569
|
debuggerModel: DebuggerModel;
|
568
570
|
frameId: Protocol.Page.FrameId|undefined;
|
569
571
|
constructor(
|
570
572
|
runtimeModel: RuntimeModel, id: Protocol.Runtime.ExecutionContextId, uniqueId: string, name: string,
|
571
|
-
origin:
|
573
|
+
origin: Platform.DevToolsPath.UrlString, isDefault: boolean, frameId?: Protocol.Page.FrameId) {
|
572
574
|
this.id = id;
|
573
575
|
this.uniqueId = uniqueId;
|
574
576
|
this.name = name;
|
@@ -157,7 +157,7 @@ export class ExtensionSidebarPane extends UI.View.SimpleView {
|
|
157
157
|
expression, true, false, evaluateOptions, securityOrigin, this.onEvaluate.bind(this, title, callback));
|
158
158
|
}
|
159
159
|
|
160
|
-
setPage(url:
|
160
|
+
setPage(url: Platform.DevToolsPath.UrlString): void {
|
161
161
|
if (this.objectPropertiesView) {
|
162
162
|
this.objectPropertiesView.detach();
|
163
163
|
delete this.objectPropertiesView;
|
@@ -54,7 +54,7 @@ import {ExtensionTraceProvider} from './ExtensionTraceProvider.js';
|
|
54
54
|
import {LanguageExtensionEndpoint} from './LanguageExtensionEndpoint.js';
|
55
55
|
import {PrivateAPI} from './ExtensionAPI.js';
|
56
56
|
|
57
|
-
const extensionOrigins: WeakMap<MessagePort,
|
57
|
+
const extensionOrigins: WeakMap<MessagePort, Platform.DevToolsPath.UrlString> = new WeakMap();
|
58
58
|
|
59
59
|
declare global {
|
60
60
|
interface Window {
|
@@ -342,7 +342,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
342
342
|
return undefined;
|
343
343
|
}
|
344
344
|
|
345
|
-
private getExtensionOrigin(port: MessagePort):
|
345
|
+
private getExtensionOrigin(port: MessagePort): Platform.DevToolsPath.UrlString {
|
346
346
|
const origin = extensionOrigins.get(port);
|
347
347
|
if (!origin) {
|
348
348
|
throw new Error('Received a message from an unregistered extension');
|
@@ -837,7 +837,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
837
837
|
this.postNotification(PrivateAPI.Events.PanelObjectSelected + 'elements');
|
838
838
|
}
|
839
839
|
|
840
|
-
sourceSelectionChanged(url:
|
840
|
+
sourceSelectionChanged(url: Platform.DevToolsPath.UrlString, range: TextUtils.TextRange.TextRange): void {
|
841
841
|
this.postNotification(PrivateAPI.Events.PanelObjectSelected + 'sources', {
|
842
842
|
startLine: range.startLine,
|
843
843
|
startColumn: range.startColumn,
|
@@ -893,7 +893,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
893
893
|
return true;
|
894
894
|
}
|
895
895
|
|
896
|
-
private registerExtension(origin:
|
896
|
+
private registerExtension(origin: Platform.DevToolsPath.UrlString, port: MessagePort): void {
|
897
897
|
if (!this.registeredExtensions.has(origin)) {
|
898
898
|
if (origin !== window.location.origin) { // Just ignore inspector frames.
|
899
899
|
console.error('Ignoring unauthorized client request from ' + origin);
|
@@ -907,7 +907,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
907
907
|
|
908
908
|
private onWindowMessage(event: MessageEvent): void {
|
909
909
|
if (event.data === 'registerExtension') {
|
910
|
-
this.registerExtension(event.origin, event.ports[0]);
|
910
|
+
this.registerExtension(event.origin as Platform.DevToolsPath.UrlString, event.ports[0]);
|
911
911
|
}
|
912
912
|
}
|
913
913
|
|
@@ -981,8 +981,9 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
981
981
|
removeLastEventListener.bind(this));
|
982
982
|
}
|
983
983
|
|
984
|
-
private expandResourcePath(extensionPath:
|
985
|
-
|
984
|
+
private expandResourcePath(extensionPath: Platform.DevToolsPath.UrlString, resourcePath: string):
|
985
|
+
Platform.DevToolsPath.UrlString {
|
986
|
+
return extensionPath + '/' + Common.ParsedURL.normalizePath(resourcePath) as Platform.DevToolsPath.UrlString;
|
986
987
|
}
|
987
988
|
|
988
989
|
evaluate(
|
@@ -992,7 +993,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
992
993
|
|undefined {
|
993
994
|
let context;
|
994
995
|
|
995
|
-
function resolveURLToFrame(url:
|
996
|
+
function resolveURLToFrame(url: Platform.DevToolsPath.UrlString): SDK.ResourceTreeModel.ResourceTreeFrame|null {
|
996
997
|
let found = null;
|
997
998
|
function hasMatchingURL(frame: SDK.ResourceTreeModel.ResourceTreeFrame): SDK.ResourceTreeModel.ResourceTreeFrame|
|
998
999
|
null {
|
@@ -1006,7 +1007,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
1006
1007
|
options = options || {};
|
1007
1008
|
let frame;
|
1008
1009
|
if (options.frameURL) {
|
1009
|
-
frame = resolveURLToFrame(options.frameURL);
|
1010
|
+
frame = resolveURLToFrame(options.frameURL as Platform.DevToolsPath.UrlString);
|
1010
1011
|
} else {
|
1011
1012
|
const target = SDK.TargetManager.TargetManager.instance().mainTarget();
|
1012
1013
|
const resourceTreeModel = target && target.model(SDK.ResourceTreeModel.ResourceTreeModel);
|
@@ -1085,7 +1086,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
1085
1086
|
return undefined;
|
1086
1087
|
}
|
1087
1088
|
|
1088
|
-
private canInspectURL(url:
|
1089
|
+
private canInspectURL(url: Platform.DevToolsPath.UrlString): boolean {
|
1089
1090
|
let parsedURL;
|
1090
1091
|
// This is only to work around invalid URLs we're occasionally getting from some tests.
|
1091
1092
|
// TODO(caseq): make sure tests supply valid URLs or we specifically handle invalid ones.
|
@@ -35,6 +35,7 @@
|
|
35
35
|
// See https://bugs.webkit.org/show_bug.cgi?id=58127 for details.
|
36
36
|
|
37
37
|
import * as Common from '../../core/common/common.js';
|
38
|
+
import type * as Platform from '../../core/platform/platform.js';
|
38
39
|
import * as SDK from '../../core/sdk/sdk.js';
|
39
40
|
import type * as Protocol from '../../generated/protocol.js';
|
40
41
|
|
@@ -346,8 +347,8 @@ export class Entry {
|
|
346
347
|
return parameters.slice();
|
347
348
|
}
|
348
349
|
|
349
|
-
private buildRequestURL(url:
|
350
|
-
return
|
350
|
+
private buildRequestURL(url: Platform.DevToolsPath.UrlString): Platform.DevToolsPath.UrlString {
|
351
|
+
return Common.ParsedURL.ParsedURL.split(url, '#', 2)[0];
|
351
352
|
}
|
352
353
|
|
353
354
|
private buildCookies(cookies: SDK.Cookie.Cookie[]): CookieDTO[] {
|
@@ -438,7 +439,7 @@ export interface Content {
|
|
438
439
|
|
439
440
|
export interface Request {
|
440
441
|
method: string;
|
441
|
-
url:
|
442
|
+
url: Platform.DevToolsPath.UrlString;
|
442
443
|
httpVersion: string;
|
443
444
|
headers: Object;
|
444
445
|
queryString: Parameter[];
|
@@ -30,12 +30,14 @@
|
|
30
30
|
|
31
31
|
import * as Common from '../../core/common/common.js';
|
32
32
|
import * as i18n from '../../core/i18n/i18n.js';
|
33
|
+
import * as Root from '../../core/root/root.js';
|
33
34
|
import * as SDK from '../../core/sdk/sdk.js';
|
34
35
|
import * as NetworkForward from '../../panels/network/forward/forward.js';
|
35
36
|
import * as UI from '../../ui/legacy/legacy.js';
|
36
|
-
import * as NetworkComponents from './components/components.js';
|
37
37
|
|
38
|
+
import * as NetworkComponents from './components/components.js';
|
38
39
|
import {EventSourceMessagesView} from './EventSourceMessagesView.js';
|
40
|
+
|
39
41
|
import type {NetworkTimeCalculator} from './NetworkTimeCalculator.js';
|
40
42
|
import {RequestCookiesView} from './RequestCookiesView.js';
|
41
43
|
import {RequestHeadersView} from './RequestHeadersView.js';
|
@@ -130,6 +132,7 @@ export class NetworkItemView extends UI.TabbedPane.TabbedPane {
|
|
130
132
|
private requestInternal: SDK.NetworkRequest.NetworkRequest;
|
131
133
|
private readonly resourceViewTabSetting: Common.Settings.Setting<NetworkForward.UIRequestLocation.UIRequestTabs>;
|
132
134
|
private readonly headersView: RequestHeadersView;
|
135
|
+
private readonly headersViewComponent: NetworkComponents.RequestHeadersView.RequestHeadersView;
|
133
136
|
private payloadView: RequestPayloadView|null;
|
134
137
|
private readonly responseView: RequestResponseView|undefined;
|
135
138
|
private cookiesView: RequestCookiesView|null;
|
@@ -149,6 +152,12 @@ export class NetworkItemView extends UI.TabbedPane.TabbedPane {
|
|
149
152
|
this.appendTab(
|
150
153
|
NetworkForward.UIRequestLocation.UIRequestTabs.Headers, i18nString(UIStrings.headers), this.headersView,
|
151
154
|
i18nString(UIStrings.headers));
|
155
|
+
this.headersViewComponent = new NetworkComponents.RequestHeadersView.RequestHeadersView(request);
|
156
|
+
if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.HEADER_OVERRIDES)) {
|
157
|
+
this.appendTab(
|
158
|
+
NetworkForward.UIRequestLocation.UIRequestTabs.HeadersComponent, i18nString(UIStrings.headers),
|
159
|
+
this.headersViewComponent, i18nString(UIStrings.headers));
|
160
|
+
}
|
152
161
|
|
153
162
|
this.payloadView = null;
|
154
163
|
void this.maybeAppendPayloadPanel();
|
@@ -451,7 +451,7 @@ export class RequestHeadersView extends UI.Widget.VBox {
|
|
451
451
|
if (headersText) {
|
452
452
|
const toggleButton = this.createHeadersToggleButton(this.showRequestHeadersText);
|
453
453
|
toggleButton.addEventListener('click', this.toggleRequestHeadersText.bind(this), false);
|
454
|
-
treeElement.listItemElement.appendChild(toggleButton);
|
454
|
+
treeElement.listItemElement.querySelector('.headers-title-left')?.appendChild(toggleButton);
|
455
455
|
}
|
456
456
|
}
|
457
457
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2022 The Chromium Authors. All rights reserved.
|
3
|
+
* Use of this source code is governed by a BSD-style license that can be
|
4
|
+
* found in the LICENSE file.
|
5
|
+
*/
|
6
|
+
|
7
|
+
.header {
|
8
|
+
background-color: var(--color-background-elevation-1);
|
9
|
+
border-bottom: var(--legacy-divider-border);
|
10
|
+
border-top: var(--legacy-divider-border);
|
11
|
+
line-height: 25px;
|
12
|
+
padding: 0 5px;
|
13
|
+
}
|
14
|
+
|
15
|
+
.header::marker {
|
16
|
+
color: rgb(110 110 110); /* stylelint-disable-line plugin/use_theme_colors */
|
17
|
+
/* See: crbug.com/1152736 for color variable migration. */
|
18
|
+
font-size: 11px;
|
19
|
+
line-height: 1;
|
20
|
+
}
|
21
|
+
|
22
|
+
.header:focus {
|
23
|
+
background-color: var(--legacy-focus-bg-color);
|
24
|
+
}
|
25
|
+
|
26
|
+
.row {
|
27
|
+
display: flex;
|
28
|
+
line-height: 20px;
|
29
|
+
padding-left: 25px;
|
30
|
+
}
|
31
|
+
|
32
|
+
.row:first-of-type {
|
33
|
+
margin-top: 2px;
|
34
|
+
}
|
35
|
+
|
36
|
+
.row:last-child {
|
37
|
+
margin-bottom: 10px;
|
38
|
+
}
|
39
|
+
|
40
|
+
.header-name {
|
41
|
+
color: var(--color-primary);
|
42
|
+
font-weight: bold;
|
43
|
+
width: 160px;
|
44
|
+
flex-shrink: 0;
|
45
|
+
}
|
46
|
+
|
47
|
+
.header-value {
|
48
|
+
word-break: break-all;
|
49
|
+
user-select: text;
|
50
|
+
}
|
51
|
+
|
52
|
+
.green-circle::before,
|
53
|
+
.red-circle::before,
|
54
|
+
.yellow-circle::before {
|
55
|
+
content: "";
|
56
|
+
display: inline-block;
|
57
|
+
width: 12px;
|
58
|
+
height: 12px;
|
59
|
+
border-radius: 6px;
|
60
|
+
vertical-align: text-top;
|
61
|
+
margin-right: 2px;
|
62
|
+
}
|
63
|
+
|
64
|
+
.green-circle::before {
|
65
|
+
background-color: var(--color-accent-green);
|
66
|
+
}
|
67
|
+
|
68
|
+
.red-circle::before {
|
69
|
+
background-color: var(--color-accent-red);
|
70
|
+
}
|
71
|
+
|
72
|
+
.yellow-circle::before {
|
73
|
+
background-color: var(--issue-color-yellow);
|
74
|
+
}
|
75
|
+
|
76
|
+
.status-with-comment {
|
77
|
+
color: var(--color-text-secondary);
|
78
|
+
}
|
@@ -0,0 +1,262 @@
|
|
1
|
+
// Copyright 2022 The Chromium Authors. All rights reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
3
|
+
// found in the LICENSE file.
|
4
|
+
|
5
|
+
import * as Common from '../../../core/common/common.js';
|
6
|
+
import * as i18n from '../../../core/i18n/i18n.js';
|
7
|
+
import {assertNotNullOrUndefined} from '../../../core/platform/platform.js';
|
8
|
+
import * as SDK from '../../../core/sdk/sdk.js';
|
9
|
+
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
10
|
+
import * as UI from '../../../ui/legacy/legacy.js';
|
11
|
+
import * as LitHtml from '../../../ui/lit-html/lit-html.js';
|
12
|
+
|
13
|
+
import requestHeadersViewStyles from './RequestHeadersView.css.js';
|
14
|
+
|
15
|
+
const {render, html} = LitHtml;
|
16
|
+
|
17
|
+
const UIStrings = {
|
18
|
+
/**
|
19
|
+
*@description Text in Request Headers View of the Network panel
|
20
|
+
*/
|
21
|
+
fromMemoryCache: '(from memory cache)',
|
22
|
+
/**
|
23
|
+
*@description Text in Request Headers View of the Network panel
|
24
|
+
*/
|
25
|
+
fromServiceWorker: '(from `service worker`)',
|
26
|
+
/**
|
27
|
+
*@description Text in Request Headers View of the Network panel
|
28
|
+
*/
|
29
|
+
fromSignedexchange: '(from signed-exchange)',
|
30
|
+
/**
|
31
|
+
*@description Text in Request Headers View of the Network panel
|
32
|
+
*/
|
33
|
+
fromPrefetchCache: '(from prefetch cache)',
|
34
|
+
/**
|
35
|
+
*@description Text in Request Headers View of the Network panel
|
36
|
+
*/
|
37
|
+
fromDiskCache: '(from disk cache)',
|
38
|
+
/**
|
39
|
+
*@description Text in Request Headers View of the Network panel
|
40
|
+
*/
|
41
|
+
fromWebBundle: '(from Web Bundle)',
|
42
|
+
/**
|
43
|
+
*@description Section header for a list of the main aspects of a http request
|
44
|
+
*/
|
45
|
+
general: 'General',
|
46
|
+
/**
|
47
|
+
*@description The URL of a request
|
48
|
+
*/
|
49
|
+
requestUrl: 'Request URL',
|
50
|
+
/**
|
51
|
+
*@description The HTTP method of a request
|
52
|
+
*/
|
53
|
+
requestMethod: 'Request Method',
|
54
|
+
/**
|
55
|
+
*@description HTTP response code
|
56
|
+
*/
|
57
|
+
statusCode: 'Status Code',
|
58
|
+
/**
|
59
|
+
*@description Text in Network Log View Columns of the Network panel
|
60
|
+
*/
|
61
|
+
remoteAddress: 'Remote Address',
|
62
|
+
/**
|
63
|
+
*@description Text in Request Headers View of the Network panel
|
64
|
+
*/
|
65
|
+
referrerPolicy: 'Referrer Policy',
|
66
|
+
};
|
67
|
+
const str_ = i18n.i18n.registerUIStrings('panels/network/components/RequestHeadersView.ts', UIStrings);
|
68
|
+
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
69
|
+
|
70
|
+
export class RequestHeadersView extends UI.Widget.VBox {
|
71
|
+
readonly #headersView = new RequestHeadersComponent();
|
72
|
+
readonly #request: SDK.NetworkRequest.NetworkRequest;
|
73
|
+
|
74
|
+
constructor(request: SDK.NetworkRequest.NetworkRequest) {
|
75
|
+
super();
|
76
|
+
this.#request = request;
|
77
|
+
this.contentElement.appendChild(this.#headersView);
|
78
|
+
}
|
79
|
+
|
80
|
+
wasShown(): void {
|
81
|
+
this.#request.addEventListener(SDK.NetworkRequest.Events.RemoteAddressChanged, this.#refreshHeadersView, this);
|
82
|
+
this.#request.addEventListener(SDK.NetworkRequest.Events.FinishedLoading, this.#refreshHeadersView, this);
|
83
|
+
this.#refreshHeadersView();
|
84
|
+
}
|
85
|
+
|
86
|
+
willHide(): void {
|
87
|
+
this.#request.removeEventListener(SDK.NetworkRequest.Events.RemoteAddressChanged, this.#refreshHeadersView, this);
|
88
|
+
this.#request.removeEventListener(SDK.NetworkRequest.Events.FinishedLoading, this.#refreshHeadersView, this);
|
89
|
+
}
|
90
|
+
|
91
|
+
#refreshHeadersView(): void {
|
92
|
+
this.#headersView.data = {
|
93
|
+
request: this.#request,
|
94
|
+
};
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
export interface RequestHeadersComponentData {
|
99
|
+
request: SDK.NetworkRequest.NetworkRequest;
|
100
|
+
}
|
101
|
+
|
102
|
+
export class RequestHeadersComponent extends HTMLElement {
|
103
|
+
static readonly litTagName = LitHtml.literal`devtools-request-headers`;
|
104
|
+
readonly #shadow = this.attachShadow({mode: 'open'});
|
105
|
+
#request?: Readonly<SDK.NetworkRequest.NetworkRequest>;
|
106
|
+
|
107
|
+
set data(data: RequestHeadersComponentData) {
|
108
|
+
this.#request = data.request;
|
109
|
+
this.#render();
|
110
|
+
}
|
111
|
+
|
112
|
+
connectedCallback(): void {
|
113
|
+
this.#shadow.adoptedStyleSheets = [requestHeadersViewStyles];
|
114
|
+
}
|
115
|
+
|
116
|
+
#render(): void {
|
117
|
+
assertNotNullOrUndefined(this.#request);
|
118
|
+
|
119
|
+
// Disabled until https://crbug.com/1079231 is fixed.
|
120
|
+
// clang-format off
|
121
|
+
render(html`
|
122
|
+
${this.#renderGeneralSection()}
|
123
|
+
`, this.#shadow, {host: this});
|
124
|
+
// clang-format on
|
125
|
+
}
|
126
|
+
|
127
|
+
#renderGeneralSection(): LitHtml.TemplateResult {
|
128
|
+
assertNotNullOrUndefined(this.#request);
|
129
|
+
|
130
|
+
let coloredCircleClassName = 'red-circle';
|
131
|
+
if (this.#request.statusCode < 300 || this.#request.statusCode === 304) {
|
132
|
+
coloredCircleClassName = 'green-circle';
|
133
|
+
} else if (this.#request.statusCode < 400) {
|
134
|
+
coloredCircleClassName = 'yellow-circle';
|
135
|
+
}
|
136
|
+
|
137
|
+
let statusText = this.#request.statusCode + ' ' + this.#request.statusText;
|
138
|
+
let statusTextHasComment = false;
|
139
|
+
if (this.#request.cachedInMemory()) {
|
140
|
+
statusText += ' ' + i18nString(UIStrings.fromMemoryCache);
|
141
|
+
statusTextHasComment = true;
|
142
|
+
} else if (this.#request.fetchedViaServiceWorker) {
|
143
|
+
statusText += ' ' + i18nString(UIStrings.fromServiceWorker);
|
144
|
+
statusTextHasComment = true;
|
145
|
+
} else if (this.#request.redirectSourceSignedExchangeInfoHasNoErrors()) {
|
146
|
+
statusText += ' ' + i18nString(UIStrings.fromSignedexchange);
|
147
|
+
statusTextHasComment = true;
|
148
|
+
} else if (this.#request.webBundleInnerRequestInfo()) {
|
149
|
+
statusText += ' ' + i18nString(UIStrings.fromWebBundle);
|
150
|
+
statusTextHasComment = true;
|
151
|
+
} else if (this.#request.fromPrefetchCache()) {
|
152
|
+
statusText += ' ' + i18nString(UIStrings.fromPrefetchCache);
|
153
|
+
statusTextHasComment = true;
|
154
|
+
} else if (this.#request.cached()) {
|
155
|
+
statusText += ' ' + i18nString(UIStrings.fromDiskCache);
|
156
|
+
statusTextHasComment = true;
|
157
|
+
}
|
158
|
+
|
159
|
+
// Disabled until https://crbug.com/1079231 is fixed.
|
160
|
+
// clang-format off
|
161
|
+
return html`
|
162
|
+
<${Category.litTagName} .data=${{name: 'general', title: i18nString(UIStrings.general)} as CategoryData}>
|
163
|
+
<div class="row">
|
164
|
+
<div class="header-name">${i18nString(UIStrings.requestUrl)}:</div>
|
165
|
+
<div class="header-value">${this.#request.url()}</div>
|
166
|
+
</div>
|
167
|
+
${this.#request.statusCode? html`
|
168
|
+
<div class="row">
|
169
|
+
<div class="header-name">${i18nString(UIStrings.requestMethod)}:</div>
|
170
|
+
<div class="header-value">${this.#request.requestMethod}</div>
|
171
|
+
</div>
|
172
|
+
<div class="row">
|
173
|
+
<div class="header-name">${i18nString(UIStrings.statusCode)}:</div>
|
174
|
+
<div class="header-value ${coloredCircleClassName} ${statusTextHasComment ? 'status-with-comment' : ''}">${statusText}</div>
|
175
|
+
</div>
|
176
|
+
` : ''}
|
177
|
+
${this.#request.remoteAddress()? html`
|
178
|
+
<div class="row">
|
179
|
+
<div class="header-name">${i18nString(UIStrings.remoteAddress)}:</div>
|
180
|
+
<div class="header-value">${this.#request.remoteAddress()}</div>
|
181
|
+
</div>
|
182
|
+
` : ''}
|
183
|
+
${this.#request.referrerPolicy()? html`
|
184
|
+
<div class="row">
|
185
|
+
<div class="header-name">${i18nString(UIStrings.referrerPolicy)}:</div>
|
186
|
+
<div class="header-value">${this.#request.referrerPolicy()}</div>
|
187
|
+
</div>
|
188
|
+
` : ''}
|
189
|
+
</${Category.litTagName}>
|
190
|
+
`;
|
191
|
+
// clang-format on
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
export interface CategoryData {
|
196
|
+
name: string;
|
197
|
+
title: Common.UIString.LocalizedString;
|
198
|
+
}
|
199
|
+
|
200
|
+
export class Category extends HTMLElement {
|
201
|
+
static readonly litTagName = LitHtml.literal`devtools-request-headers-category`;
|
202
|
+
readonly #shadow = this.attachShadow({mode: 'open'});
|
203
|
+
#expandedSetting?: Common.Settings.Setting<boolean>;
|
204
|
+
#title: Common.UIString.LocalizedString = Common.UIString.LocalizedEmptyString;
|
205
|
+
|
206
|
+
connectedCallback(): void {
|
207
|
+
this.#shadow.adoptedStyleSheets = [requestHeadersViewStyles];
|
208
|
+
}
|
209
|
+
|
210
|
+
set data(data: CategoryData) {
|
211
|
+
this.#title = data.title;
|
212
|
+
this.#expandedSetting =
|
213
|
+
Common.Settings.Settings.instance().createSetting('request-info-' + data.name + '-category-expanded', true);
|
214
|
+
this.#render();
|
215
|
+
}
|
216
|
+
|
217
|
+
#render(): void {
|
218
|
+
// Disabled until https://crbug.com/1079231 is fixed.
|
219
|
+
// clang-format off
|
220
|
+
render(html`
|
221
|
+
<details ?open=${this.#expandedSetting ? this.#expandedSetting.get() : true} @toggle=${this.#onToggle}>
|
222
|
+
<summary class="header" @keydown=${this.#onSummaryKeyDown}>${this.#title}</summary>
|
223
|
+
<slot></slot>
|
224
|
+
</details>
|
225
|
+
`, this.#shadow, {host: this});
|
226
|
+
// clang-format on
|
227
|
+
}
|
228
|
+
|
229
|
+
#onSummaryKeyDown(event: KeyboardEvent): void {
|
230
|
+
if (!event.target) {
|
231
|
+
return;
|
232
|
+
}
|
233
|
+
const summaryElement = event.target as HTMLElement;
|
234
|
+
const detailsElement = summaryElement.parentElement as HTMLDetailsElement;
|
235
|
+
if (!detailsElement) {
|
236
|
+
throw new Error('<details> element is not found for a <summary> element');
|
237
|
+
}
|
238
|
+
switch (event.key) {
|
239
|
+
case 'ArrowLeft':
|
240
|
+
detailsElement.open = false;
|
241
|
+
break;
|
242
|
+
case 'ArrowRight':
|
243
|
+
detailsElement.open = true;
|
244
|
+
break;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
#onToggle(event: Event): void {
|
249
|
+
this.#expandedSetting?.set((event.target as HTMLDetailsElement).open);
|
250
|
+
}
|
251
|
+
}
|
252
|
+
|
253
|
+
ComponentHelpers.CustomElements.defineComponent('devtools-request-headers', RequestHeadersComponent);
|
254
|
+
ComponentHelpers.CustomElements.defineComponent('devtools-request-headers-category', Category);
|
255
|
+
|
256
|
+
declare global {
|
257
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
258
|
+
interface HTMLElementTagNameMap {
|
259
|
+
'devtools-request-headers': RequestHeadersComponent;
|
260
|
+
'devtools-request-headers-category': Category;
|
261
|
+
}
|
262
|
+
}
|
@@ -2,8 +2,10 @@
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
3
3
|
// found in the LICENSE file.
|
4
4
|
|
5
|
+
import * as RequestHeadersView from './RequestHeadersView.js';
|
5
6
|
import * as RequestTrustTokensView from './RequestTrustTokensView.js';
|
6
7
|
|
7
8
|
export {
|
9
|
+
RequestHeadersView,
|
8
10
|
RequestTrustTokensView,
|
9
11
|
};
|
@@ -70,7 +70,7 @@
|
|
70
70
|
flex: none;
|
71
71
|
}
|
72
72
|
|
73
|
-
.network-log-grid.data-grid
|
73
|
+
.network-log-grid.data-grid tbody {
|
74
74
|
background: transparent;
|
75
75
|
}
|
76
76
|
|
@@ -397,8 +397,8 @@
|
|
397
397
|
/* This is part of the large color block declared above, but should not be
|
398
398
|
extracted out. */
|
399
399
|
/* stylelint-disable no-descending-specificity */
|
400
|
-
.network-log-grid.data-grid
|
401
|
-
.network-log-grid.data-grid:focus
|
400
|
+
.network-log-grid.data-grid tbody tr.revealed.selected,
|
401
|
+
.network-log-grid.data-grid:focus tbody tr.revealed.selected,
|
402
402
|
.network-log-grid.data-grid:focus tr.selected .network-dim-cell,
|
403
403
|
.network-log-grid.data-grid tr.selected .network-dim-cell,
|
404
404
|
.network-log-grid.data-grid:focus tr.selected .initiator-column .devtools-link,
|
@@ -86,6 +86,12 @@ const UIStrings = {
|
|
86
86
|
*@description Text in Call Stack Sidebar Pane of the Sources panel when some call frames have warnings
|
87
87
|
*/
|
88
88
|
callFrameWarnings: 'Some call frames have warnings',
|
89
|
+
/**
|
90
|
+
* @description A contex menu item in the Call Stack Sidebar Pane. "Restart" is a verb and
|
91
|
+
* "frame" is a noun. "Frame" refers to an individual item in the call stack, i.e. a call frame.
|
92
|
+
* The user opens this context menu by selecting a specific call frame in the call stack sidebar pane.
|
93
|
+
*/
|
94
|
+
restartFrame: 'Restart frame',
|
89
95
|
};
|
90
96
|
const str_ = i18n.i18n.registerUIStrings('panels/sources/CallStackSidebarPane.ts', UIStrings);
|
91
97
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
@@ -384,6 +390,13 @@ export class CallStackSidebarPane extends UI.View.SimpleView implements UI.Conte
|
|
384
390
|
return;
|
385
391
|
}
|
386
392
|
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
393
|
+
const debuggerCallFrame = itemToCallFrame.get(item);
|
394
|
+
if (debuggerCallFrame) {
|
395
|
+
contextMenu.defaultSection().appendItem(i18nString(UIStrings.restartFrame), () => {
|
396
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.StackFrameRestarted);
|
397
|
+
void debuggerCallFrame.restart();
|
398
|
+
}, !debuggerCallFrame.canBeRestarted);
|
399
|
+
}
|
387
400
|
contextMenu.defaultSection().appendItem(i18nString(UIStrings.copyStackTrace), this.copyStackTrace.bind(this));
|
388
401
|
if (item.uiLocation) {
|
389
402
|
this.appendIgnoreListURLContextMenuItems(contextMenu, item.uiLocation.uiSourceCode);
|
@@ -311,13 +311,14 @@ export class OpenLinearMemoryInspector extends UI.Widget.VBox implements UI.Cont
|
|
311
311
|
}
|
312
312
|
|
313
313
|
private isMemoryObjectProperty(obj: SDK.RemoteObject.RemoteObject): boolean {
|
314
|
-
const
|
314
|
+
const isWasmOrBuffer = obj.type === 'object' && obj.subtype &&
|
315
315
|
LinearMemoryInspector.LinearMemoryInspectorController.ACCEPTED_MEMORY_TYPES.includes(obj.subtype);
|
316
|
-
if (
|
316
|
+
if (isWasmOrBuffer) {
|
317
317
|
return true;
|
318
318
|
}
|
319
319
|
|
320
|
-
|
320
|
+
const isWasmDWARF = obj instanceof Bindings.DebuggerLanguagePlugins.ValueNode;
|
321
|
+
if (isWasmDWARF) {
|
321
322
|
return obj.inspectableAddress !== undefined;
|
322
323
|
}
|
323
324
|
|
@@ -130,6 +130,7 @@ export class DataGridImpl<T> extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
130
130
|
[x: string]: Element,
|
131
131
|
};
|
132
132
|
scrollContainerInternal: Element;
|
133
|
+
private dataContainerInternal: Element;
|
133
134
|
private readonly dataTable: Element;
|
134
135
|
protected inline: boolean;
|
135
136
|
private columnsArray: ColumnDescriptor[];
|
@@ -190,8 +191,9 @@ export class DataGridImpl<T> extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
190
191
|
|
191
192
|
this.dataTableHeaders = {};
|
192
193
|
|
193
|
-
this.
|
194
|
-
this.dataTable = this.
|
194
|
+
this.dataContainerInternal = this.element.createChild('div', 'data-container');
|
195
|
+
this.dataTable = this.dataContainerInternal.createChild('table', 'data');
|
196
|
+
this.scrollContainerInternal = this.dataContainerInternal;
|
195
197
|
|
196
198
|
// FIXME: Add a createCallback which is different from editCallback and has different
|
197
199
|
// behavior when creating a new node.
|
@@ -1539,6 +1541,18 @@ export class DataGridImpl<T> extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
1539
1541
|
return this.topFillerRow;
|
1540
1542
|
}
|
1541
1543
|
|
1544
|
+
// Note on the following methods:
|
1545
|
+
// The header row is a child of the scrollable container, and uses position: sticky
|
1546
|
+
// so it can visually obscure other elements below it in the grid. We need to manually
|
1547
|
+
// subtract the header's height when calculating the actual client area in which
|
1548
|
+
// data rows are visible. However, if a caller has set a different scroll container
|
1549
|
+
// then we report 0 height and the caller is expected to ensure their chosen scroll
|
1550
|
+
// container's height matches the visible scrollable data area as seen by the user.
|
1551
|
+
|
1552
|
+
protected headerHeightInScroller(): number {
|
1553
|
+
return this.scrollContainer === this.dataContainerInternal ? this.headerHeight() : 0;
|
1554
|
+
}
|
1555
|
+
|
1542
1556
|
protected headerHeight(): number {
|
1543
1557
|
return this.dataTableHeadInternal.offsetHeight;
|
1544
1558
|
}
|
@@ -172,7 +172,7 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
|
|
172
172
|
delete this.updateAnimationFrameId;
|
173
173
|
}
|
174
174
|
|
175
|
-
const clientHeight = this.scrollContainer.clientHeight - this.
|
175
|
+
const clientHeight = this.scrollContainer.clientHeight - this.headerHeightInScroller();
|
176
176
|
let scrollTop: number = this.scrollContainer.scrollTop;
|
177
177
|
const currentScrollTop = scrollTop;
|
178
178
|
const maxScrollTop = Math.max(0, this.contentHeight() - clientHeight);
|
@@ -249,7 +249,7 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
|
|
249
249
|
}
|
250
250
|
const toY = fromY + node.nodeSelfHeight();
|
251
251
|
let scrollTop: number = this.scrollContainer.scrollTop;
|
252
|
-
const visibleHeight = this.scrollContainer.offsetHeight - this.
|
252
|
+
const visibleHeight = this.scrollContainer.offsetHeight - this.headerHeightInScroller();
|
253
253
|
if (scrollTop > fromY) {
|
254
254
|
scrollTop = fromY;
|
255
255
|
this.stickToBottom = false;
|
package/package.json
CHANGED