chrome-devtools-mcp 0.2.0 → 0.2.2
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/README.md +27 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Progress.js +60 -53
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/GdpClient.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +5 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js +2 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +11 -10
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +24 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js +29 -24
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +9 -15
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RemoteObject.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ResourceTreeModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RuntimeModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ServiceWorkerManager.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +4 -31
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TraceObject.js +5 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.js +6 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.js +259 -179
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/UnitFormatters.js +10 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +14 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ContentProviderBasedProject.js +6 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/FormatterWorkerPool.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/ModelImpl.js +4 -9
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/Processor.js +17 -9
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/AuctionWorkletsHandler.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/FramesHandler.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/LayoutShiftsHandler.js +3 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/MetaHandler.js +10 -9
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/ScreenshotsHandler.js +0 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/ScriptsHandler.js +4 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/UserInteractionsHandler.js +2 -10
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/UserTimingsHandler.js +3 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/SamplesIntegrator.js +8 -6
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/CLSCulprits.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DocumentLatency.js +3 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DuplicatedJavaScript.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/INPBreakdown.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ImageDelivery.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPBreakdown.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPDiscovery.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ModernHTTP.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/NetworkDependencyTree.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/RenderBlocking.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/types/TraceEvents.js +21 -21
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +5 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/trace_source_maps_resolver.js +1 -1
- package/build/src/McpContext.js +60 -10
- package/build/src/McpResponse.js +5 -4
- package/build/src/WaitForHelper.js +127 -0
- package/build/src/browser.js +12 -9
- package/build/src/index.js +20 -21
- package/build/src/logger.js +1 -0
- package/build/src/tools/input.js +5 -6
- package/build/src/tools/pages.js +2 -3
- package/build/src/tools/performance.js +16 -14
- package/build/src/tools/script.js +1 -2
- package/build/src/trace-processing/parse.js +23 -14
- package/package.json +15 -16
- package/build/src/waitForHelpers.js +0 -109
package/README.md
CHANGED
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://npmjs.org/package/chrome-devtools-mcp)
|
|
4
4
|
|
|
5
|
-
`chrome-devtools-mcp`
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
`chrome-devtools-mcp` lets your coding agent (such as Gemini, Claude, Cursor or Copilot)
|
|
6
|
+
control and inspect a live Chrome browser. It acts as a Model-Context-Protocol
|
|
7
|
+
(MCP) server, giving your AI coding assistant access to the full power of
|
|
8
|
+
Chrome DevTools for reliable automation, in-depth debugging, and performance analysis.
|
|
8
9
|
|
|
9
10
|
## Key features
|
|
10
11
|
|
|
11
12
|
- **Get performance insights**: Uses [Chrome
|
|
12
13
|
DevTools](https://github.com/ChromeDevTools/devtools-frontend) to record
|
|
13
|
-
traces and extract performance insights.
|
|
14
|
+
traces and extract actionable performance insights.
|
|
14
15
|
- **Advanced browser debugging**: Analyze network requests, take screenshots and
|
|
15
16
|
check the browser console.
|
|
16
17
|
- **Reliable automation**. Uses
|
|
@@ -48,7 +49,7 @@ Add the following config to your MCP client:
|
|
|
48
49
|
> [!NOTE]
|
|
49
50
|
> Using `chrome-devtools-mcp@latest` ensures that your MCP client will always use the latest version of the Chrome DevTools MCP server.
|
|
50
51
|
|
|
51
|
-
### MCP Client
|
|
52
|
+
### MCP Client configuration
|
|
52
53
|
|
|
53
54
|
<details>
|
|
54
55
|
<summary>Claude Code</summary>
|
|
@@ -77,7 +78,15 @@ claude mcp add chrome-devtools npx chrome-devtools-mcp@latest
|
|
|
77
78
|
|
|
78
79
|
<details>
|
|
79
80
|
<summary>Cursor</summary>
|
|
80
|
-
|
|
81
|
+
|
|
82
|
+
**Click the button to install:**
|
|
83
|
+
|
|
84
|
+
[<img src="https://cursor.com/deeplink/mcp-install-dark.svg" alt="Install in Cursor">](https://cursor.com/en/install-mcp?name=chrome-devtools&config=eyJjb21tYW5kIjoibnB4IGNocm9tZS1kZXZ0b29scy1tY3BAbGF0ZXN0In0%3D)
|
|
85
|
+
|
|
86
|
+
**Or install manually:**
|
|
87
|
+
|
|
88
|
+
Go to `Cursor Settings` -> `MCP` -> `New MCP Server`. Use the config provided above.
|
|
89
|
+
|
|
81
90
|
</details>
|
|
82
91
|
|
|
83
92
|
<details>
|
|
@@ -156,10 +165,9 @@ The Chrome DevTools MCP server supports the following configuration option:
|
|
|
156
165
|
- **Default:** `false`
|
|
157
166
|
|
|
158
167
|
- **`--channel`**
|
|
159
|
-
Specify a different Chrome channel that should be used.
|
|
168
|
+
Specify a different Chrome channel that should be used. The default is the stable channel version.
|
|
160
169
|
- **Type:** string
|
|
161
170
|
- **Choices:** `stable`, `canary`, `beta`, `dev`
|
|
162
|
-
- **Default:** `stable`
|
|
163
171
|
|
|
164
172
|
<!-- END AUTO GENERATED OPTIONS -->
|
|
165
173
|
|
|
@@ -197,3 +205,14 @@ The user data directory is not cleared between runs and shared across
|
|
|
197
205
|
all instances of `chrome-devtools-mcp`. Set the `isolated` option to `true`
|
|
198
206
|
to use a temporary user data dir instead which will be cleared automatically after
|
|
199
207
|
the browser is closed.
|
|
208
|
+
|
|
209
|
+
## Known limitations
|
|
210
|
+
|
|
211
|
+
### Operating system sandboxes
|
|
212
|
+
|
|
213
|
+
Some MCP clients allow sandboxing the MCP server using macOS Seatbelt or Linux
|
|
214
|
+
containers. If sandboxes are enabled, `chrome-devtools-mcp` is not able to start
|
|
215
|
+
Chrome that requires permissions to create its own sandboxes. As a workaround,
|
|
216
|
+
either disable sandboxing for `chrome-devtools-mcp` in your MCP client or use
|
|
217
|
+
`--connect-url` to connect to a Chrome instance that you start manually outside
|
|
218
|
+
of the MCP client sandbox.
|
|
@@ -2,19 +2,11 @@
|
|
|
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
|
export class Progress {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
incrementWorked(_worked) {
|
|
12
|
-
}
|
|
13
|
-
done() {
|
|
14
|
-
}
|
|
15
|
-
isCanceled() {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
5
|
+
totalWork = 0;
|
|
6
|
+
worked = 0;
|
|
7
|
+
title = undefined;
|
|
8
|
+
canceled = false;
|
|
9
|
+
done = false;
|
|
18
10
|
}
|
|
19
11
|
export class CompositeProgress {
|
|
20
12
|
parent;
|
|
@@ -24,14 +16,14 @@ export class CompositeProgress {
|
|
|
24
16
|
this.parent = parent;
|
|
25
17
|
this.#children = [];
|
|
26
18
|
this.#childrenDone = 0;
|
|
27
|
-
this.parent.
|
|
28
|
-
this.parent.
|
|
19
|
+
this.parent.totalWork = 1;
|
|
20
|
+
this.parent.worked = 0;
|
|
29
21
|
}
|
|
30
22
|
childDone() {
|
|
31
23
|
if (++this.#childrenDone !== this.#children.length) {
|
|
32
24
|
return;
|
|
33
25
|
}
|
|
34
|
-
this.parent.done
|
|
26
|
+
this.parent.done = true;
|
|
35
27
|
}
|
|
36
28
|
createSubProgress(weight) {
|
|
37
29
|
const child = new SubProgress(this, weight);
|
|
@@ -43,12 +35,12 @@ export class CompositeProgress {
|
|
|
43
35
|
let done = 0;
|
|
44
36
|
for (let i = 0; i < this.#children.length; ++i) {
|
|
45
37
|
const child = this.#children[i];
|
|
46
|
-
if (child.
|
|
47
|
-
done += child.
|
|
38
|
+
if (child.totalWork) {
|
|
39
|
+
done += child.weight * child.worked / child.totalWork;
|
|
48
40
|
}
|
|
49
|
-
totalWeights += child.
|
|
41
|
+
totalWeights += child.weight;
|
|
50
42
|
}
|
|
51
|
-
this.parent.
|
|
43
|
+
this.parent.worked = done / totalWeights;
|
|
52
44
|
}
|
|
53
45
|
}
|
|
54
46
|
export class SubProgress {
|
|
@@ -62,76 +54,91 @@ export class SubProgress {
|
|
|
62
54
|
this.#worked = 0;
|
|
63
55
|
this.#totalWork = 0;
|
|
64
56
|
}
|
|
65
|
-
|
|
66
|
-
return this.#composite.parent.
|
|
57
|
+
get canceled() {
|
|
58
|
+
return this.#composite.parent.canceled;
|
|
67
59
|
}
|
|
68
|
-
|
|
69
|
-
this.#composite.parent.
|
|
60
|
+
set title(title) {
|
|
61
|
+
this.#composite.parent.title = title;
|
|
70
62
|
}
|
|
71
|
-
done() {
|
|
72
|
-
|
|
63
|
+
set done(done) {
|
|
64
|
+
if (!done) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.worked = this.#totalWork;
|
|
73
68
|
this.#composite.childDone();
|
|
74
69
|
}
|
|
75
|
-
|
|
70
|
+
set totalWork(totalWork) {
|
|
76
71
|
this.#totalWork = totalWork;
|
|
77
72
|
this.#composite.update();
|
|
78
73
|
}
|
|
79
|
-
|
|
74
|
+
set worked(worked) {
|
|
80
75
|
this.#worked = worked;
|
|
81
|
-
if (typeof title !== 'undefined') {
|
|
82
|
-
this.setTitle(title);
|
|
83
|
-
}
|
|
84
76
|
this.#composite.update();
|
|
85
77
|
}
|
|
86
|
-
|
|
87
|
-
this.setWorked(this.#worked + (worked || 1));
|
|
88
|
-
}
|
|
89
|
-
getWeight() {
|
|
78
|
+
get weight() {
|
|
90
79
|
return this.#weight;
|
|
91
80
|
}
|
|
92
|
-
|
|
81
|
+
get worked() {
|
|
93
82
|
return this.#worked;
|
|
94
83
|
}
|
|
95
|
-
|
|
84
|
+
get totalWork() {
|
|
96
85
|
return this.#totalWork;
|
|
97
86
|
}
|
|
98
87
|
}
|
|
99
88
|
export class ProgressProxy {
|
|
100
89
|
#delegate;
|
|
101
90
|
#doneCallback;
|
|
102
|
-
|
|
91
|
+
#updateCallback;
|
|
92
|
+
constructor(delegate, doneCallback, updateCallback) {
|
|
103
93
|
this.#delegate = delegate;
|
|
104
94
|
this.#doneCallback = doneCallback;
|
|
95
|
+
this.#updateCallback = updateCallback;
|
|
105
96
|
}
|
|
106
|
-
|
|
107
|
-
return this.#delegate ? this.#delegate.
|
|
97
|
+
get canceled() {
|
|
98
|
+
return this.#delegate ? this.#delegate.canceled : false;
|
|
108
99
|
}
|
|
109
|
-
|
|
100
|
+
set title(title) {
|
|
110
101
|
if (this.#delegate) {
|
|
111
|
-
this.#delegate.
|
|
102
|
+
this.#delegate.title = title;
|
|
103
|
+
}
|
|
104
|
+
if (this.#updateCallback) {
|
|
105
|
+
this.#updateCallback();
|
|
112
106
|
}
|
|
113
107
|
}
|
|
114
|
-
|
|
108
|
+
get title() {
|
|
109
|
+
return this.#delegate?.title ?? '';
|
|
110
|
+
}
|
|
111
|
+
set done(done) {
|
|
115
112
|
if (this.#delegate) {
|
|
116
|
-
this.#delegate.done
|
|
113
|
+
this.#delegate.done = done;
|
|
117
114
|
}
|
|
118
|
-
if (this.#doneCallback) {
|
|
115
|
+
if (done && this.#doneCallback) {
|
|
119
116
|
this.#doneCallback();
|
|
120
117
|
}
|
|
121
118
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
this.#delegate.setTotalWork(totalWork);
|
|
125
|
-
}
|
|
119
|
+
get done() {
|
|
120
|
+
return this.#delegate ? this.#delegate.done : false;
|
|
126
121
|
}
|
|
127
|
-
|
|
122
|
+
set totalWork(totalWork) {
|
|
128
123
|
if (this.#delegate) {
|
|
129
|
-
this.#delegate.
|
|
124
|
+
this.#delegate.totalWork = totalWork;
|
|
130
125
|
}
|
|
126
|
+
if (this.#updateCallback) {
|
|
127
|
+
this.#updateCallback();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
get totalWork() {
|
|
131
|
+
return this.#delegate ? this.#delegate.totalWork : 0;
|
|
131
132
|
}
|
|
132
|
-
|
|
133
|
+
set worked(worked) {
|
|
133
134
|
if (this.#delegate) {
|
|
134
|
-
this.#delegate.
|
|
135
|
+
this.#delegate.worked = worked;
|
|
135
136
|
}
|
|
137
|
+
if (this.#updateCallback) {
|
|
138
|
+
this.#updateCallback?.();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
get worked() {
|
|
142
|
+
return this.#delegate ? this.#delegate.worked : 0;
|
|
136
143
|
}
|
|
137
144
|
}
|
|
@@ -39,7 +39,7 @@ function normalizeBadgeName(name) {
|
|
|
39
39
|
}
|
|
40
40
|
export const GOOGLE_DEVELOPER_PROGRAM_PROFILE_LINK = 'https://developers.google.com/profile/u/me';
|
|
41
41
|
async function makeHttpRequest(request) {
|
|
42
|
-
if (!Root.Runtime.hostConfig.devToolsGdpProfiles?.enabled) {
|
|
42
|
+
if (!Root.Runtime.hostConfig.devToolsGdpProfiles?.enabled || Root.Runtime.hostConfig.isOffTheRecord) {
|
|
43
43
|
return null;
|
|
44
44
|
}
|
|
45
45
|
const response = await new Promise(resolve => {
|
|
@@ -418,7 +418,11 @@ export var Action;
|
|
|
418
418
|
Action[Action["AiAssistanceOpenedFromPerformanceInsight"] = 182] = "AiAssistanceOpenedFromPerformanceInsight";
|
|
419
419
|
Action[Action["AiAssistanceOpenedFromPerformanceFullButton"] = 183] = "AiAssistanceOpenedFromPerformanceFullButton";
|
|
420
420
|
Action[Action["AiCodeCompletionResponseServedFromCache"] = 184] = "AiCodeCompletionResponseServedFromCache";
|
|
421
|
-
Action[Action["
|
|
421
|
+
Action[Action["AiCodeCompletionRequestTriggered"] = 185] = "AiCodeCompletionRequestTriggered";
|
|
422
|
+
Action[Action["AiCodeCompletionSuggestionDisplayed"] = 186] = "AiCodeCompletionSuggestionDisplayed";
|
|
423
|
+
Action[Action["AiCodeCompletionSuggestionAccepted"] = 187] = "AiCodeCompletionSuggestionAccepted";
|
|
424
|
+
Action[Action["AiCodeCompletionError"] = 188] = "AiCodeCompletionError";
|
|
425
|
+
Action[Action["MAX_VALUE"] = 189] = "MAX_VALUE";
|
|
422
426
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
423
427
|
})(Action || (Action = {}));
|
|
424
428
|
export var PanelCodes;
|
|
@@ -694,7 +698,6 @@ export var DevtoolsExperiments;
|
|
|
694
698
|
DevtoolsExperiments[DevtoolsExperiments["just-my-code"] = 65] = "just-my-code";
|
|
695
699
|
DevtoolsExperiments[DevtoolsExperiments["use-source-map-scopes"] = 76] = "use-source-map-scopes";
|
|
696
700
|
DevtoolsExperiments[DevtoolsExperiments["timeline-show-postmessage-events"] = 86] = "timeline-show-postmessage-events";
|
|
697
|
-
DevtoolsExperiments[DevtoolsExperiments["timeline-save-as-gz"] = 108] = "timeline-save-as-gz";
|
|
698
701
|
DevtoolsExperiments[DevtoolsExperiments["timeline-enhanced-traces"] = 90] = "timeline-enhanced-traces";
|
|
699
702
|
DevtoolsExperiments[DevtoolsExperiments["timeline-compiled-sources"] = 91] = "timeline-compiled-sources";
|
|
700
703
|
DevtoolsExperiments[DevtoolsExperiments["timeline-debug-mode"] = 93] = "timeline-debug-mode";
|
|
@@ -81,10 +81,12 @@ export class InspectorBackend {
|
|
|
81
81
|
}
|
|
82
82
|
let connectionFactory;
|
|
83
83
|
export class Connection {
|
|
84
|
+
// on message from browser
|
|
84
85
|
setOnMessage(_onMessage) {
|
|
85
86
|
}
|
|
86
87
|
setOnDisconnect(_onDisconnect) {
|
|
87
88
|
}
|
|
89
|
+
// send raw CDP message to browser
|
|
88
90
|
sendRawMessage(_message) {
|
|
89
91
|
}
|
|
90
92
|
disconnect() {
|
|
@@ -5,7 +5,7 @@ import * as Platform from '../platform/platform.js';
|
|
|
5
5
|
import { CSSMetadata, cssMetadata } from './CSSMetadata.js';
|
|
6
6
|
import { CSSProperty } from './CSSProperty.js';
|
|
7
7
|
import * as PropertyParser from './CSSPropertyParser.js';
|
|
8
|
-
import { AnchorFunctionMatcher, AngleMatcher, AttributeMatcher, AutoBaseMatcher, BaseVariableMatcher, BezierMatcher, BinOpMatcher, ColorMatcher, ColorMixMatcher, defaultValueForCSSType, EnvFunctionMatcher, FlexGridMatcher, GridTemplateMatcher, LengthMatcher, LightDarkColorMatcher, LinearGradientMatcher, LinkableNameMatcher, localEvalCSS, MathFunctionMatcher, PositionAnchorMatcher, PositionTryMatcher, RelativeColorChannelMatcher, ShadowMatcher, StringMatcher, URLMatcher, VariableMatcher } from './CSSPropertyParserMatchers.js';
|
|
8
|
+
import { AnchorFunctionMatcher, AngleMatcher, AttributeMatcher, AutoBaseMatcher, BaseVariableMatcher, BezierMatcher, BinOpMatcher, ColorMatcher, ColorMixMatcher, CustomFunctionMatcher, defaultValueForCSSType, EnvFunctionMatcher, FlexGridMatcher, GridTemplateMatcher, LengthMatcher, LightDarkColorMatcher, LinearGradientMatcher, LinkableNameMatcher, localEvalCSS, MathFunctionMatcher, PositionAnchorMatcher, PositionTryMatcher, RelativeColorChannelMatcher, ShadowMatcher, StringMatcher, URLMatcher, VariableMatcher } from './CSSPropertyParserMatchers.js';
|
|
9
9
|
import { CSSFontPaletteValuesRule, CSSFunctionRule, CSSKeyframeRule, CSSKeyframesRule, CSSPositionTryRule, CSSPropertyRule, CSSStyleRule, } from './CSSRule.js';
|
|
10
10
|
import { CSSStyleDeclaration, Type } from './CSSStyleDeclaration.js';
|
|
11
11
|
function containsStyle(styles, query) {
|
|
@@ -713,6 +713,7 @@ export class CSSMatchedStyles {
|
|
|
713
713
|
new PositionTryMatcher(),
|
|
714
714
|
new LengthMatcher(),
|
|
715
715
|
new MathFunctionMatcher(),
|
|
716
|
+
new CustomFunctionMatcher(),
|
|
716
717
|
new AutoBaseMatcher(),
|
|
717
718
|
new BinOpMatcher(),
|
|
718
719
|
new RelativeColorChannelMatcher(),
|
|
@@ -997,9 +998,9 @@ class DOMInheritanceCascade {
|
|
|
997
998
|
if (!nodeCascade) {
|
|
998
999
|
return null;
|
|
999
1000
|
}
|
|
1000
|
-
return this
|
|
1001
|
+
return this.#computeCSSVariable(nodeCascade, variableName);
|
|
1001
1002
|
}
|
|
1002
|
-
|
|
1003
|
+
#computeCSSVariable(nodeCascade, variableName, sccRecord = new SCCRecord()) {
|
|
1003
1004
|
const availableCSSVariables = this.#availableCSSVariables.get(nodeCascade);
|
|
1004
1005
|
const computedCSSVariables = this.#computedCSSVariables.get(nodeCascade);
|
|
1005
1006
|
if (!computedCSSVariables || !availableCSSVariables?.has(variableName)) {
|
|
@@ -1029,7 +1030,7 @@ class DOMInheritanceCascade {
|
|
|
1029
1030
|
if (!ast) {
|
|
1030
1031
|
return null;
|
|
1031
1032
|
}
|
|
1032
|
-
return this
|
|
1033
|
+
return this.#walkTree(nodeCascade, ast, definedValue.declaration.style, variableName, sccRecord, definedValue.declaration);
|
|
1033
1034
|
}
|
|
1034
1035
|
computeAttribute(style, attributeName, type) {
|
|
1035
1036
|
this.ensureInitialized();
|
|
@@ -1037,7 +1038,7 @@ class DOMInheritanceCascade {
|
|
|
1037
1038
|
if (!nodeCascade) {
|
|
1038
1039
|
return null;
|
|
1039
1040
|
}
|
|
1040
|
-
return this
|
|
1041
|
+
return this.#computeAttribute(nodeCascade, style, attributeName, type, new SCCRecord());
|
|
1041
1042
|
}
|
|
1042
1043
|
attributeValueAsType(style, attributeName, type) {
|
|
1043
1044
|
const rawValue = this.#matchedStyles.rawAttributeValueFromStyle(style, attributeName);
|
|
@@ -1055,9 +1056,9 @@ class DOMInheritanceCascade {
|
|
|
1055
1056
|
if (!ast) {
|
|
1056
1057
|
return null;
|
|
1057
1058
|
}
|
|
1058
|
-
return this
|
|
1059
|
+
return this.#walkTree(nodeCascade, ast, style, `attr(${attributeName})`, sccRecord)?.value ?? null;
|
|
1059
1060
|
}
|
|
1060
|
-
|
|
1061
|
+
#computeAttribute(nodeCascade, style, attributeName, type, sccRecord = new SCCRecord()) {
|
|
1061
1062
|
if (type.isCSSTokens) {
|
|
1062
1063
|
const value = this.attributeValueWithSubstitutions(nodeCascade, style, attributeName, sccRecord);
|
|
1063
1064
|
if (value !== null && localEvalCSS(value, type.type) !== null) {
|
|
@@ -1067,7 +1068,7 @@ class DOMInheritanceCascade {
|
|
|
1067
1068
|
}
|
|
1068
1069
|
return this.attributeValueAsType(style, attributeName, type.type);
|
|
1069
1070
|
}
|
|
1070
|
-
|
|
1071
|
+
#walkTree(outerNodeCascade, ast, parentStyle, substitutionName, sccRecord, declaration) {
|
|
1071
1072
|
const record = sccRecord.add(outerNodeCascade, substitutionName);
|
|
1072
1073
|
const computedCSSVariablesMap = this.#computedCSSVariables;
|
|
1073
1074
|
const innerNodeCascade = this.#styleToNodeCascade.get(parentStyle);
|
|
@@ -1081,7 +1082,7 @@ class DOMInheritanceCascade {
|
|
|
1081
1082
|
// bubbling up the minimum discovery time whenever we close a cycle.
|
|
1082
1083
|
const matching = PropertyParser.BottomUpTreeMatching.walk(ast, [
|
|
1083
1084
|
new BaseVariableMatcher(match => {
|
|
1084
|
-
const { value, mayFallback } = recurseWithCycleDetection(match.name, nodeCascade => this
|
|
1085
|
+
const { value, mayFallback } = recurseWithCycleDetection(match.name, nodeCascade => this.#computeCSSVariable(nodeCascade, match.name, sccRecord)?.value ?? null);
|
|
1085
1086
|
if (!mayFallback || value !== null) {
|
|
1086
1087
|
return value;
|
|
1087
1088
|
}
|
|
@@ -1268,7 +1269,7 @@ class DOMInheritanceCascade {
|
|
|
1268
1269
|
for (const variableName of variableNames) {
|
|
1269
1270
|
const prevValue = accumulatedCSSVariables.get(variableName);
|
|
1270
1271
|
accumulatedCSSVariables.delete(variableName);
|
|
1271
|
-
const computedValue = this
|
|
1272
|
+
const computedValue = this.#computeCSSVariable(nodeCascade, variableName);
|
|
1272
1273
|
if (prevValue && computedValue?.value === prevValue.value) {
|
|
1273
1274
|
computedValue.declaration = prevValue.declaration;
|
|
1274
1275
|
}
|
package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js
CHANGED
|
@@ -750,9 +750,6 @@ export class LinkableNameMatcher extends matcherBase(LinkableNameMatch) {
|
|
|
750
750
|
if (!parentNode) {
|
|
751
751
|
return null;
|
|
752
752
|
}
|
|
753
|
-
if (parentNode.name === 'CallExpression' && node.name === 'VariableName') {
|
|
754
|
-
return new LinkableNameMatch(text, node, "function" /* LinkableNameProperties.FUNCTION */);
|
|
755
|
-
}
|
|
756
753
|
if (!(propertyName && LinkableNameMatcher.isLinkableNameProperty(propertyName))) {
|
|
757
754
|
return null;
|
|
758
755
|
}
|
|
@@ -906,7 +903,7 @@ export class LengthMatcher extends matcherBase(LengthMatch) {
|
|
|
906
903
|
return new LengthMatch(text, node, unit);
|
|
907
904
|
}
|
|
908
905
|
}
|
|
909
|
-
export class
|
|
906
|
+
export class BaseFunctionMatch {
|
|
910
907
|
text;
|
|
911
908
|
node;
|
|
912
909
|
func;
|
|
@@ -917,6 +914,8 @@ export class MathFunctionMatch {
|
|
|
917
914
|
this.func = func;
|
|
918
915
|
this.args = args;
|
|
919
916
|
}
|
|
917
|
+
}
|
|
918
|
+
export class MathFunctionMatch extends BaseFunctionMatch {
|
|
920
919
|
isArithmeticFunctionCall() {
|
|
921
920
|
const func = this.func;
|
|
922
921
|
switch (func) {
|
|
@@ -969,6 +968,27 @@ export class MathFunctionMatcher extends matcherBase(MathFunctionMatch) {
|
|
|
969
968
|
return match;
|
|
970
969
|
}
|
|
971
970
|
}
|
|
971
|
+
export class CustomFunctionMatch extends BaseFunctionMatch {
|
|
972
|
+
}
|
|
973
|
+
// clang-format off
|
|
974
|
+
export class CustomFunctionMatcher extends matcherBase(CustomFunctionMatch) {
|
|
975
|
+
// clang-format on
|
|
976
|
+
matches(node, matching) {
|
|
977
|
+
if (node.name !== 'CallExpression') {
|
|
978
|
+
return null;
|
|
979
|
+
}
|
|
980
|
+
const callee = matching.ast.text(node.getChild('VariableName'));
|
|
981
|
+
if (!callee?.startsWith('--')) {
|
|
982
|
+
return null;
|
|
983
|
+
}
|
|
984
|
+
const args = ASTUtils.callArgs(node);
|
|
985
|
+
if (args.some(arg => arg.length === 0 || matching.hasUnresolvedSubstitutionsRange(arg[0], arg[arg.length - 1]))) {
|
|
986
|
+
return null;
|
|
987
|
+
}
|
|
988
|
+
const text = matching.ast.text(node);
|
|
989
|
+
return new CustomFunctionMatch(text, node, callee, args);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
972
992
|
export class FlexGridMatch {
|
|
973
993
|
text;
|
|
974
994
|
node;
|
package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js
CHANGED
|
@@ -27,7 +27,7 @@ export class EnhancedTracesParser {
|
|
|
27
27
|
}
|
|
28
28
|
parseEnhancedTrace() {
|
|
29
29
|
for (const event of this.#trace.traceEvents) {
|
|
30
|
-
if (this.
|
|
30
|
+
if (this.isTracingStartedInBrowser(event)) {
|
|
31
31
|
// constructs all targets by devtools.timeline TracingStartedInBrowser
|
|
32
32
|
const data = event.args?.data;
|
|
33
33
|
for (const frame of data.frames) {
|
|
@@ -53,7 +53,7 @@ export class EnhancedTracesParser {
|
|
|
53
53
|
this.#scriptToFrame.set(this.getScriptIsolateId(data.isolate, data.scriptId), data.frame);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
else if (this.
|
|
56
|
+
else if (this.isRundownScriptCompiled(event)) {
|
|
57
57
|
// Set up script to v8 context mapping
|
|
58
58
|
const data = event.args?.data;
|
|
59
59
|
this.#scriptToV8Context.set(this.getScriptIsolateId(data.isolate, data.scriptId), data.v8context);
|
|
@@ -64,7 +64,7 @@ export class EnhancedTracesParser {
|
|
|
64
64
|
this.#targets.push({
|
|
65
65
|
targetId: frameId,
|
|
66
66
|
type: data.frameType,
|
|
67
|
-
isolate: data.isolate,
|
|
67
|
+
isolate: String(data.isolate),
|
|
68
68
|
pid: event.pid,
|
|
69
69
|
url: data.url,
|
|
70
70
|
});
|
|
@@ -80,34 +80,37 @@ export class EnhancedTracesParser {
|
|
|
80
80
|
isDefault: data.isDefault,
|
|
81
81
|
type: data.contextType,
|
|
82
82
|
},
|
|
83
|
-
isolate: data.isolate,
|
|
83
|
+
isolate: String(data.isolate),
|
|
84
|
+
name: data.origin,
|
|
85
|
+
uniqueId: `${data.v8context}-${data.isolate}`,
|
|
84
86
|
});
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
|
-
else if (this.
|
|
89
|
+
else if (this.isRundownScript(event)) {
|
|
88
90
|
this.#scriptRundownEvents.push(event);
|
|
89
91
|
const data = event.args.data;
|
|
90
92
|
// Add script
|
|
91
|
-
if (!this.#scripts.find(script => script.scriptId === String(data.scriptId) && script.isolate === data.isolate)) {
|
|
93
|
+
if (!this.#scripts.find(script => script.scriptId === String(data.scriptId) && script.isolate === String(data.isolate))) {
|
|
92
94
|
this.#scripts.push({
|
|
93
95
|
scriptId: String(data.scriptId),
|
|
94
|
-
isolate: data.isolate,
|
|
96
|
+
isolate: String(data.isolate),
|
|
97
|
+
buildId: '',
|
|
95
98
|
executionContextId: data.executionContextId,
|
|
96
99
|
startLine: data.startLine ?? 0,
|
|
97
100
|
startColumn: data.startColumn ?? 0,
|
|
98
101
|
endLine: data.endLine ?? 0,
|
|
99
102
|
endColumn: data.endColumn ?? 0,
|
|
100
|
-
hash: data.hash,
|
|
103
|
+
hash: data.hash ?? '',
|
|
101
104
|
isModule: data.isModule,
|
|
102
|
-
url: data.url,
|
|
105
|
+
url: data.url ?? '',
|
|
103
106
|
hasSourceURL: data.hasSourceUrl,
|
|
104
|
-
sourceURL: data.sourceUrl,
|
|
107
|
+
sourceURL: data.sourceUrl ?? '',
|
|
105
108
|
sourceMapURL: data.sourceMapUrl,
|
|
106
109
|
pid: event.pid,
|
|
107
110
|
});
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
|
-
else if (this.
|
|
113
|
+
else if (this.isRundownScriptSource(event)) {
|
|
111
114
|
// Set up script to source text and length mapping
|
|
112
115
|
const data = event.args.data;
|
|
113
116
|
const scriptIsolateId = this.getScriptIsolateId(data.isolate, data.scriptId);
|
|
@@ -166,10 +169,10 @@ export class EnhancedTracesParser {
|
|
|
166
169
|
// put in the aux data
|
|
167
170
|
const linkedExecutionContext = this.#executionContexts.find(context => context.id === script.executionContextId && context.isolate === script.isolate);
|
|
168
171
|
if (linkedExecutionContext) {
|
|
169
|
-
script.
|
|
172
|
+
script.executionContextAuxData = linkedExecutionContext.auxData;
|
|
170
173
|
// If a script successfully mapped to an execution context and aux data, link script to frame
|
|
171
|
-
if (script.
|
|
172
|
-
this.#scriptToFrame.set(scriptIsolateId, script.
|
|
174
|
+
if (script.executionContextAuxData?.frameId) {
|
|
175
|
+
this.#scriptToFrame.set(scriptIsolateId, script.executionContextAuxData?.frameId);
|
|
173
176
|
}
|
|
174
177
|
}
|
|
175
178
|
});
|
|
@@ -225,25 +228,25 @@ export class EnhancedTracesParser {
|
|
|
225
228
|
return sourceMap;
|
|
226
229
|
}
|
|
227
230
|
getScriptIsolateId(isolate, scriptId) {
|
|
228
|
-
return scriptId
|
|
231
|
+
return `${scriptId}@${isolate}`;
|
|
229
232
|
}
|
|
230
233
|
getExecutionContextIsolateId(isolate, executionContextId) {
|
|
231
|
-
return executionContextId
|
|
234
|
+
return `${executionContextId}@${isolate}`;
|
|
232
235
|
}
|
|
233
236
|
isTraceEvent(event) {
|
|
234
|
-
return 'cat' in event && 'pid' in event &&
|
|
235
|
-
'
|
|
237
|
+
return 'cat' in event && 'pid' in event && 'args' in event &&
|
|
238
|
+
'data' in event.args;
|
|
236
239
|
}
|
|
237
|
-
|
|
240
|
+
isRundownScriptCompiled(event) {
|
|
238
241
|
return this.isTraceEvent(event) && event.cat === 'disabled-by-default-devtools.target-rundown';
|
|
239
242
|
}
|
|
240
|
-
|
|
243
|
+
isRundownScript(event) {
|
|
241
244
|
return this.isTraceEvent(event) && event.cat === 'disabled-by-default-devtools.v8-source-rundown';
|
|
242
245
|
}
|
|
243
|
-
|
|
246
|
+
isRundownScriptSource(event) {
|
|
244
247
|
return this.isTraceEvent(event) && event.cat === 'disabled-by-default-devtools.v8-source-rundown-sources';
|
|
245
248
|
}
|
|
246
|
-
|
|
249
|
+
isTracingStartedInBrowser(event) {
|
|
247
250
|
return this.isTraceEvent(event) && event.cat === 'disabled-by-default-devtools.timeline' &&
|
|
248
251
|
event.name === 'TracingStartedInBrowser';
|
|
249
252
|
}
|
|
@@ -279,8 +282,8 @@ export class EnhancedTracesParser {
|
|
|
279
282
|
// Put all of the scripts under respective targets with collected information
|
|
280
283
|
for (const script of scripts) {
|
|
281
284
|
const scriptExecutionContextIsolateId = this.getExecutionContextIsolateId(script.isolate, script.executionContextId);
|
|
282
|
-
const scriptFrameId = script.
|
|
283
|
-
if (script.
|
|
285
|
+
const scriptFrameId = script.executionContextAuxData?.frameId;
|
|
286
|
+
if (script.executionContextAuxData?.frameId && targetIds.has(scriptFrameId)) {
|
|
284
287
|
targetToScripts.get(scriptFrameId)?.push(script);
|
|
285
288
|
executionContextIsolateToTarget.set(scriptExecutionContextIsolateId, scriptFrameId);
|
|
286
289
|
}
|
|
@@ -328,12 +331,14 @@ export class EnhancedTracesParser {
|
|
|
328
331
|
id: script.executionContextId,
|
|
329
332
|
origin: '',
|
|
330
333
|
v8Context: '',
|
|
334
|
+
name: '',
|
|
331
335
|
auxData: {
|
|
332
336
|
frameId: targetId,
|
|
333
337
|
isDefault: false,
|
|
334
338
|
type: 'type',
|
|
335
339
|
},
|
|
336
340
|
isolate: script.isolate,
|
|
341
|
+
uniqueId: `${targetId}-${script.isolate}`,
|
|
337
342
|
};
|
|
338
343
|
executionContexts.push(artificialContext);
|
|
339
344
|
}
|