chrome-devtools-mcp 0.9.0 → 0.10.1
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 +14 -9
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Console.js +1 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ParsedURL.js +10 -20
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/SegmentedRange.js +1 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Settings.js +3 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/StringOutputStream.js +1 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/AidaClient.js +19 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/DispatchHttpRequestClient.js +54 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/GdpClient.js +6 -51
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHost.js +2 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostAPI.js +32 -29
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +14 -6
- package/build/node_modules/chrome-devtools-frontend/front_end/core/host/host.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/CDPConnection.js +17 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js +68 -188
- package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/protocol_client.js +2 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/AnimationModel.js +1 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +3 -3
- 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/CSSProperty.js +3 -6
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +14 -10
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStyleDeclaration.js +4 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js +5 -33
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Connections.js +9 -46
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +1 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +1 -2
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js +17 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +59 -37
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +5 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +102 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +2 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk-meta.js +8 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +1 -39
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +58 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js +46 -45
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +10 -25
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerWorkspaceBinding.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/ProfileTreeModel.js +6 -7
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTraceModel.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/NetworkRequestsHandler.js +12 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/types/TraceEvents.js +3 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/mcp/mcp.js +14 -0
- package/build/src/DevToolsConnectionAdapter.js +1 -0
- package/build/src/DevtoolsUtils.js +44 -0
- package/build/src/McpContext.js +133 -21
- package/build/src/McpResponse.js +33 -22
- package/build/src/PageCollector.js +21 -9
- package/build/src/browser.js +8 -8
- package/build/src/cli.js +8 -3
- package/build/src/formatters/networkFormatter.js +2 -2
- package/build/src/formatters/snapshotFormatter.js +18 -6
- package/build/src/main.js +7 -2
- package/build/src/third_party/THIRD_PARTY_NOTICES +72 -52
- package/build/src/third_party/index.js +12687 -6053
- package/build/src/tools/emulation.js +37 -44
- package/build/src/tools/input.js +36 -6
- package/build/src/tools/network.js +27 -5
- package/build/src/tools/pages.js +60 -34
- package/build/src/tools/performance.js +5 -2
- package/build/src/tools/screenshot.js +2 -1
- package/build/src/tools/snapshot.js +13 -4
- package/build/src/trace-processing/parse.js +6 -16
- package/build/src/utils/keyboard.js +291 -0
- package/package.json +7 -6
|
@@ -2,13 +2,9 @@
|
|
|
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
|
import * as InspectorBackendCommands from '../../generated/InspectorBackendCommands.js';
|
|
5
|
+
import { CDPErrorStatus } from './CDPConnection.js';
|
|
5
6
|
import { ConnectionTransport } from './ConnectionTransport.js';
|
|
6
7
|
import { NodeURL } from './NodeURL.js';
|
|
7
|
-
export const DevToolsStubErrorCode = -32015;
|
|
8
|
-
// TODO(dgozman): we are not reporting generic errors in tests, but we should
|
|
9
|
-
// instead report them and just have some expected errors in test expectations.
|
|
10
|
-
const GenericErrorCode = -32000;
|
|
11
|
-
const ConnectionClosedErrorCode = -32001;
|
|
12
8
|
export const splitQualifiedName = (string) => {
|
|
13
9
|
const [domain, eventName] = string.split('.');
|
|
14
10
|
return [domain, eventName];
|
|
@@ -18,7 +14,6 @@ export const qualifyName = (domain, name) => {
|
|
|
18
14
|
};
|
|
19
15
|
export class InspectorBackend {
|
|
20
16
|
agentPrototypes = new Map();
|
|
21
|
-
#initialized = false;
|
|
22
17
|
#eventParameterNamesForDomain = new Map();
|
|
23
18
|
typeMap = new Map();
|
|
24
19
|
enumMap = new Map();
|
|
@@ -49,9 +44,6 @@ export class InspectorBackend {
|
|
|
49
44
|
static reportProtocolWarning(error, messageObject) {
|
|
50
45
|
console.warn(error + ': ' + JSON.stringify(messageObject));
|
|
51
46
|
}
|
|
52
|
-
isInitialized() {
|
|
53
|
-
return this.#initialized;
|
|
54
|
-
}
|
|
55
47
|
agentPrototype(domain) {
|
|
56
48
|
let prototype = this.agentPrototypes.get(domain);
|
|
57
49
|
if (!prototype) {
|
|
@@ -63,7 +55,6 @@ export class InspectorBackend {
|
|
|
63
55
|
registerCommand(method, parameters, replyArgs, description) {
|
|
64
56
|
const [domain, command] = splitQualifiedName(method);
|
|
65
57
|
this.agentPrototype(domain).registerCommand(command, parameters, replyArgs, description);
|
|
66
|
-
this.#initialized = true;
|
|
67
58
|
}
|
|
68
59
|
registerEnum(type, values) {
|
|
69
60
|
const [domain, name] = splitQualifiedName(type);
|
|
@@ -75,17 +66,14 @@ export class InspectorBackend {
|
|
|
75
66
|
// @ts-expect-error globalThis global namespace pollution
|
|
76
67
|
globalThis.Protocol[domain][name] = values;
|
|
77
68
|
this.enumMap.set(type, values);
|
|
78
|
-
this.#initialized = true;
|
|
79
69
|
}
|
|
80
70
|
registerType(method, parameters) {
|
|
81
71
|
this.typeMap.set(method, parameters);
|
|
82
|
-
this.#initialized = true;
|
|
83
72
|
}
|
|
84
73
|
registerEvent(eventName, params) {
|
|
85
74
|
const domain = eventName.split('.')[0];
|
|
86
75
|
const eventParameterNames = this.getOrCreateEventParameterNamesForDomain(domain);
|
|
87
76
|
eventParameterNames.set(eventName, params);
|
|
88
|
-
this.#initialized = true;
|
|
89
77
|
}
|
|
90
78
|
}
|
|
91
79
|
export const test = {
|
|
@@ -125,6 +113,8 @@ export class SessionRouter {
|
|
|
125
113
|
#pendingLongPollingMessageIds = new Set();
|
|
126
114
|
#sessions = new Map();
|
|
127
115
|
#pendingScripts = [];
|
|
116
|
+
#callbacks = new Map();
|
|
117
|
+
#observers = new Set();
|
|
128
118
|
constructor(connection) {
|
|
129
119
|
this.#connection = connection;
|
|
130
120
|
test.deprecatedRunAfterPendingDispatches = this.deprecatedRunAfterPendingDispatches.bind(this);
|
|
@@ -135,45 +125,43 @@ export class SessionRouter {
|
|
|
135
125
|
if (session) {
|
|
136
126
|
session.target.dispose(reason);
|
|
137
127
|
}
|
|
128
|
+
this.#observers.forEach(observer => observer.onDisconnect(reason));
|
|
138
129
|
});
|
|
139
130
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
this.#sessions.set(sessionId, { target, callbacks: new Map(), proxyConnection });
|
|
131
|
+
observe(observer) {
|
|
132
|
+
this.#observers.add(observer);
|
|
133
|
+
}
|
|
134
|
+
unobserve(observer) {
|
|
135
|
+
this.#observers.delete(observer);
|
|
136
|
+
}
|
|
137
|
+
registerSession(target, sessionId) {
|
|
138
|
+
this.#sessions.set(sessionId, { target });
|
|
152
139
|
}
|
|
153
140
|
unregisterSession(sessionId) {
|
|
154
141
|
const session = this.#sessions.get(sessionId);
|
|
155
142
|
if (!session) {
|
|
156
143
|
return;
|
|
157
144
|
}
|
|
158
|
-
for (const
|
|
159
|
-
|
|
145
|
+
for (const { resolve, method, sessionId: callbackSessionId } of this.#callbacks.values()) {
|
|
146
|
+
if (sessionId !== callbackSessionId) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
resolve({
|
|
150
|
+
error: {
|
|
151
|
+
message: `Session is unregistering, can\'t dispatch pending call to ${method}`,
|
|
152
|
+
code: CDPErrorStatus.SESSION_NOT_FOUND,
|
|
153
|
+
}
|
|
154
|
+
});
|
|
160
155
|
}
|
|
161
156
|
this.#sessions.delete(sessionId);
|
|
162
157
|
}
|
|
163
|
-
getTargetBySessionId(sessionId) {
|
|
164
|
-
const session = this.#sessions.get(sessionId ? sessionId : '');
|
|
165
|
-
if (!session) {
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
return session.target;
|
|
169
|
-
}
|
|
170
158
|
nextMessageId() {
|
|
171
159
|
return this.#lastMessageId++;
|
|
172
160
|
}
|
|
173
161
|
connection() {
|
|
174
162
|
return this.#connection;
|
|
175
163
|
}
|
|
176
|
-
|
|
164
|
+
send(method, params, sessionId) {
|
|
177
165
|
const messageId = this.nextMessageId();
|
|
178
166
|
const messageObject = {
|
|
179
167
|
id: messageId,
|
|
@@ -189,23 +177,28 @@ export class SessionRouter {
|
|
|
189
177
|
test.dumpProtocol('frontend: ' + JSON.stringify(messageObject));
|
|
190
178
|
}
|
|
191
179
|
if (test.onMessageSent) {
|
|
180
|
+
const domain = method.split('.')[0];
|
|
192
181
|
const paramsObject = JSON.parse(JSON.stringify(params || {}));
|
|
193
|
-
test.onMessageSent({ domain, method, params: paramsObject, id: messageId, sessionId }
|
|
182
|
+
test.onMessageSent({ domain, method, params: paramsObject, id: messageId, sessionId });
|
|
194
183
|
}
|
|
195
184
|
++this.#pendingResponsesCount;
|
|
196
185
|
if (LongPollingMethods.has(method)) {
|
|
197
186
|
this.#pendingLongPollingMessageIds.add(messageId);
|
|
198
187
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
session.callbacks.set(messageId, { callback, method });
|
|
204
|
-
this.#connection.sendRawMessage(JSON.stringify(messageObject));
|
|
188
|
+
return new Promise(resolve => {
|
|
189
|
+
this.#callbacks.set(messageId, { resolve, method, sessionId });
|
|
190
|
+
this.#connection.sendRawMessage(JSON.stringify(messageObject));
|
|
191
|
+
});
|
|
205
192
|
}
|
|
206
193
|
sendRawMessageForTesting(method, params, callback, sessionId = '') {
|
|
207
|
-
|
|
208
|
-
|
|
194
|
+
void this.send(method, params, sessionId).then(response => {
|
|
195
|
+
if ('error' in response && response.error) {
|
|
196
|
+
callback?.(response.error, null);
|
|
197
|
+
}
|
|
198
|
+
else if ('result' in response) {
|
|
199
|
+
callback?.(null, response.result);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
209
202
|
}
|
|
210
203
|
onMessage(message) {
|
|
211
204
|
if (test.dumpProtocol) {
|
|
@@ -213,64 +206,35 @@ export class SessionRouter {
|
|
|
213
206
|
}
|
|
214
207
|
if (test.onMessageReceived) {
|
|
215
208
|
const messageObjectCopy = JSON.parse((typeof message === 'string') ? message : JSON.stringify(message));
|
|
216
|
-
test.onMessageReceived(messageObjectCopy
|
|
209
|
+
test.onMessageReceived(messageObjectCopy);
|
|
217
210
|
}
|
|
218
211
|
const messageObject = ((typeof message === 'string') ? JSON.parse(message) : message);
|
|
219
|
-
// Send all messages to proxy connections.
|
|
220
|
-
let suppressUnknownMessageErrors = false;
|
|
221
|
-
for (const session of this.#sessions.values()) {
|
|
222
|
-
if (!session.proxyConnection) {
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
if (!session.proxyConnection.onMessage) {
|
|
226
|
-
InspectorBackend.reportProtocolError('Protocol Error: the session has a proxyConnection with no _onMessage', messageObject);
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
|
-
session.proxyConnection.onMessage(messageObject);
|
|
230
|
-
suppressUnknownMessageErrors = true;
|
|
231
|
-
}
|
|
232
212
|
const sessionId = messageObject.sessionId || '';
|
|
233
213
|
const session = this.#sessions.get(sessionId);
|
|
234
|
-
if (
|
|
235
|
-
// In the DevTools MCP case, we may share the transport with puppeteer so we silently
|
|
236
|
-
// ignore unknown sessions.
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
// If this message is directly for the target controlled by the proxy connection, don't handle it.
|
|
240
|
-
if (session.proxyConnection) {
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
if (session.target.getNeedsNodeJSPatching()) {
|
|
214
|
+
if (session?.target.getNeedsNodeJSPatching()) {
|
|
244
215
|
NodeURL.patch(messageObject);
|
|
245
216
|
}
|
|
246
|
-
if (messageObject.id !== undefined) { // just a response for some request
|
|
247
|
-
const callback =
|
|
248
|
-
|
|
217
|
+
if ('id' in messageObject && messageObject.id !== undefined) { // just a response for some request
|
|
218
|
+
const callback = this.#callbacks.get(messageObject.id);
|
|
219
|
+
this.#callbacks.delete(messageObject.id);
|
|
249
220
|
if (!callback) {
|
|
250
|
-
|
|
251
|
-
// Ignore the errors that are sent as responses after the session closes.
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
if (!suppressUnknownMessageErrors) {
|
|
255
|
-
InspectorBackend.reportProtocolError('Protocol Error: the message with wrong id', messageObject);
|
|
256
|
-
}
|
|
221
|
+
// Ignore messages with unknown IDs, we might see puppeteer proxied messages here.
|
|
257
222
|
return;
|
|
258
223
|
}
|
|
259
|
-
callback.
|
|
224
|
+
callback.resolve(messageObject);
|
|
260
225
|
--this.#pendingResponsesCount;
|
|
261
226
|
this.#pendingLongPollingMessageIds.delete(messageObject.id);
|
|
262
227
|
if (this.#pendingScripts.length && !this.hasOutstandingNonLongPollingRequests()) {
|
|
263
228
|
this.deprecatedRunAfterPendingDispatches();
|
|
264
229
|
}
|
|
265
230
|
}
|
|
266
|
-
else {
|
|
267
|
-
if (messageObject.method === undefined) {
|
|
268
|
-
InspectorBackend.reportProtocolError('Protocol Error: the message without method', messageObject);
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
231
|
+
else if ('method' in messageObject) {
|
|
271
232
|
// This cast is justified as we just checked for the presence of messageObject.method.
|
|
272
|
-
|
|
273
|
-
|
|
233
|
+
session?.target.dispatch(messageObject);
|
|
234
|
+
this.#observers.forEach(observer => observer.onEvent(messageObject));
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
InspectorBackend.reportProtocolError('Protocol Error: the message without method', messageObject);
|
|
274
238
|
}
|
|
275
239
|
}
|
|
276
240
|
hasOutstandingNonLongPollingRequests() {
|
|
@@ -299,22 +263,6 @@ export class SessionRouter {
|
|
|
299
263
|
}
|
|
300
264
|
}
|
|
301
265
|
}
|
|
302
|
-
static dispatchConnectionError(callback, method) {
|
|
303
|
-
const error = {
|
|
304
|
-
message: `Connection is closed, can\'t dispatch pending call to ${method}`,
|
|
305
|
-
code: ConnectionClosedErrorCode,
|
|
306
|
-
data: null,
|
|
307
|
-
};
|
|
308
|
-
window.setTimeout(() => callback(error, null), 0);
|
|
309
|
-
}
|
|
310
|
-
static dispatchUnregisterSessionError({ callback, method }) {
|
|
311
|
-
const error = {
|
|
312
|
-
message: `Session is unregistering, can\'t dispatch pending call to ${method}`,
|
|
313
|
-
code: ConnectionClosedErrorCode,
|
|
314
|
-
data: null,
|
|
315
|
-
};
|
|
316
|
-
window.setTimeout(() => callback(error, null), 0);
|
|
317
|
-
}
|
|
318
266
|
}
|
|
319
267
|
export class TargetBase {
|
|
320
268
|
needsNodeJSPatching;
|
|
@@ -626,6 +574,12 @@ export class TargetBase {
|
|
|
626
574
|
return this.needsNodeJSPatching;
|
|
627
575
|
}
|
|
628
576
|
}
|
|
577
|
+
/** These are not logged as console.error */
|
|
578
|
+
const IGNORED_ERRORS = new Set([
|
|
579
|
+
CDPErrorStatus.DEVTOOLS_STUB_ERROR,
|
|
580
|
+
CDPErrorStatus.SERVER_ERROR,
|
|
581
|
+
CDPErrorStatus.SESSION_NOT_FOUND,
|
|
582
|
+
]);
|
|
629
583
|
/**
|
|
630
584
|
* This is a class that serves as the prototype for a domains #agents (every target
|
|
631
585
|
* has it's own set of #agents). The InspectorBackend keeps an instance of this class
|
|
@@ -636,113 +590,39 @@ export class TargetBase {
|
|
|
636
590
|
* of the invoke_enable, etc. methods that the front-end uses.
|
|
637
591
|
*/
|
|
638
592
|
class AgentPrototype {
|
|
639
|
-
replyArgs;
|
|
640
593
|
description = '';
|
|
641
594
|
metadata;
|
|
642
595
|
domain;
|
|
643
596
|
target;
|
|
644
597
|
constructor(domain) {
|
|
645
|
-
this.replyArgs = {};
|
|
646
598
|
this.domain = domain;
|
|
647
599
|
this.metadata = {};
|
|
648
600
|
}
|
|
649
601
|
registerCommand(methodName, parameters, replyArgs, description) {
|
|
650
602
|
const domainAndMethod = qualifyName(this.domain, methodName);
|
|
651
|
-
function sendMessagePromise(...args) {
|
|
652
|
-
return AgentPrototype.prototype.sendMessageToBackendPromise.call(this, domainAndMethod, parameters, args);
|
|
653
|
-
}
|
|
654
|
-
// @ts-expect-error Method code generation
|
|
655
|
-
this[methodName] = sendMessagePromise;
|
|
656
603
|
this.metadata[domainAndMethod] = { parameters, description, replyArgs };
|
|
657
604
|
function invoke(request = {}) {
|
|
658
605
|
return this.invoke(domainAndMethod, request);
|
|
659
606
|
}
|
|
660
607
|
// @ts-expect-error Method code generation
|
|
661
608
|
this['invoke_' + methodName] = invoke;
|
|
662
|
-
this.replyArgs[domainAndMethod] = replyArgs;
|
|
663
|
-
}
|
|
664
|
-
prepareParameters(method, parameters, args, errorCallback) {
|
|
665
|
-
const params = {};
|
|
666
|
-
let hasParams = false;
|
|
667
|
-
for (const param of parameters) {
|
|
668
|
-
const paramName = param.name;
|
|
669
|
-
const typeName = param.type;
|
|
670
|
-
const optionalFlag = param.optional;
|
|
671
|
-
if (!args.length && !optionalFlag) {
|
|
672
|
-
errorCallback(`Protocol Error: Invalid number of arguments for method '${method}' call. ` +
|
|
673
|
-
`It must have the following arguments ${JSON.stringify(parameters)}'.`);
|
|
674
|
-
return null;
|
|
675
|
-
}
|
|
676
|
-
const value = args.shift();
|
|
677
|
-
if (optionalFlag && typeof value === 'undefined') {
|
|
678
|
-
continue;
|
|
679
|
-
}
|
|
680
|
-
const expectedJSType = typeName === 'array' ? 'object' : typeName;
|
|
681
|
-
if (typeof value !== expectedJSType) {
|
|
682
|
-
errorCallback(`Protocol Error: Invalid type of argument '${paramName}' for method '${method}' call. ` +
|
|
683
|
-
`It must be '${typeName}' but it is '${typeof value}'.`);
|
|
684
|
-
return null;
|
|
685
|
-
}
|
|
686
|
-
params[paramName] = value;
|
|
687
|
-
hasParams = true;
|
|
688
|
-
}
|
|
689
|
-
if (args.length) {
|
|
690
|
-
errorCallback(`Protocol Error: Extra ${args.length} arguments in a call to method '${method}'.`);
|
|
691
|
-
return null;
|
|
692
|
-
}
|
|
693
|
-
return hasParams ? params : null;
|
|
694
|
-
}
|
|
695
|
-
sendMessageToBackendPromise(method, parameters, args) {
|
|
696
|
-
let errorMessage;
|
|
697
|
-
function onError(message) {
|
|
698
|
-
console.error(message);
|
|
699
|
-
errorMessage = message;
|
|
700
|
-
}
|
|
701
|
-
const params = this.prepareParameters(method, parameters, args, onError);
|
|
702
|
-
if (errorMessage) {
|
|
703
|
-
return Promise.resolve(null);
|
|
704
|
-
}
|
|
705
|
-
return new Promise(resolve => {
|
|
706
|
-
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
|
|
707
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
708
|
-
const callback = (error, result) => {
|
|
709
|
-
if (error) {
|
|
710
|
-
if (!test.suppressRequestErrors && error.code !== DevToolsStubErrorCode && error.code !== GenericErrorCode &&
|
|
711
|
-
error.code !== ConnectionClosedErrorCode) {
|
|
712
|
-
console.error('Request ' + method + ' failed. ' + JSON.stringify(error));
|
|
713
|
-
}
|
|
714
|
-
resolve(null);
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
|
-
const args = this.replyArgs[method];
|
|
718
|
-
resolve(result && args.length ? result[args[0]] : undefined);
|
|
719
|
-
};
|
|
720
|
-
const router = this.target.router();
|
|
721
|
-
if (!router) {
|
|
722
|
-
SessionRouter.dispatchConnectionError(callback, method);
|
|
723
|
-
}
|
|
724
|
-
else {
|
|
725
|
-
router.sendMessage(this.target.sessionId, this.domain, method, params, callback);
|
|
726
|
-
}
|
|
727
|
-
});
|
|
728
609
|
}
|
|
729
610
|
invoke(method, request) {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
611
|
+
const router = this.target.router();
|
|
612
|
+
if (!router) {
|
|
613
|
+
return Promise.resolve({ result: null, getError: () => `Connection is closed, can\'t dispatch pending call to ${method}` });
|
|
614
|
+
}
|
|
615
|
+
return router.send(method, request, this.target.sessionId).then(response => {
|
|
616
|
+
if ('error' in response && response.error) {
|
|
617
|
+
if (!test.suppressRequestErrors && !IGNORED_ERRORS.has(response.error.code)) {
|
|
618
|
+
console.error('Request ' + method + ' failed. ' + JSON.stringify(response.error));
|
|
735
619
|
}
|
|
736
|
-
|
|
737
|
-
fulfill({ ...result, getError: () => errorMessage });
|
|
738
|
-
};
|
|
739
|
-
const router = this.target.router();
|
|
740
|
-
if (!router) {
|
|
741
|
-
SessionRouter.dispatchConnectionError(callback, method);
|
|
620
|
+
return { getError: () => response.error.message };
|
|
742
621
|
}
|
|
743
|
-
|
|
744
|
-
|
|
622
|
+
if ('result' in response) {
|
|
623
|
+
return { ...response.result, getError: () => undefined };
|
|
745
624
|
}
|
|
625
|
+
return { getError: () => undefined };
|
|
746
626
|
});
|
|
747
627
|
}
|
|
748
628
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Copyright 2019 The Chromium Authors
|
|
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
|
+
import * as CDPConnection from './CDPConnection.js';
|
|
4
5
|
import * as ConnectionTransport from './ConnectionTransport.js';
|
|
5
6
|
import * as InspectorBackend from './InspectorBackend.js';
|
|
6
7
|
import * as NodeURL from './NodeURL.js';
|
|
7
|
-
export { ConnectionTransport, InspectorBackend, NodeURL, };
|
|
8
|
+
export { CDPConnection, ConnectionTransport, InspectorBackend, NodeURL, };
|
|
@@ -678,12 +678,11 @@ export class AnimationGroup {
|
|
|
678
678
|
#id;
|
|
679
679
|
#scrollNode;
|
|
680
680
|
#animations;
|
|
681
|
-
#paused;
|
|
681
|
+
#paused = false;
|
|
682
682
|
constructor(animationModel, id, animations) {
|
|
683
683
|
this.#animationModel = animationModel;
|
|
684
684
|
this.#id = id;
|
|
685
685
|
this.#animations = animations;
|
|
686
|
-
this.#paused = false;
|
|
687
686
|
}
|
|
688
687
|
isScrollDriven() {
|
|
689
688
|
return Boolean(this.#animations[0]?.viewOrScrollTimeline());
|
|
@@ -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, CustomFunctionMatcher, defaultValueForCSSType, EnvFunctionMatcher,
|
|
8
|
+
import { AnchorFunctionMatcher, AngleMatcher, AttributeMatcher, AutoBaseMatcher, BaseVariableMatcher, BezierMatcher, BinOpMatcher, ColorMatcher, ColorMixMatcher, CustomFunctionMatcher, defaultValueForCSSType, EnvFunctionMatcher, FlexGridMasonryMatcher, 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) {
|
|
@@ -242,7 +242,7 @@ export class CSSMatchedStyles {
|
|
|
242
242
|
for (const inheritedResult of inheritedPayload) {
|
|
243
243
|
inheritedResult.matchedCSSRules = cleanUserAgentPayload(inheritedResult.matchedCSSRules);
|
|
244
244
|
}
|
|
245
|
-
this.#environmentVariables = await this.cssModel().
|
|
245
|
+
this.#environmentVariables = await this.cssModel().getEnvironmentVariables();
|
|
246
246
|
this.#mainDOMCascade = await this.buildMainCascade(inlinePayload, attributesPayload, matchedPayload, inheritedPayload, animationStylesPayload, transitionsStylePayload, inheritedAnimatedPayload);
|
|
247
247
|
[this.#pseudoDOMCascades, this.#customHighlightPseudoDOMCascades] =
|
|
248
248
|
this.buildPseudoCascades(pseudoPayload, inheritedPseudoPayload);
|
|
@@ -714,7 +714,7 @@ export class CSSMatchedStyles {
|
|
|
714
714
|
new LinearGradientMatcher(),
|
|
715
715
|
new AnchorFunctionMatcher(),
|
|
716
716
|
new PositionAnchorMatcher(),
|
|
717
|
-
new
|
|
717
|
+
new FlexGridMasonryMatcher(),
|
|
718
718
|
new PositionTryMatcher(),
|
|
719
719
|
new LengthMatcher(),
|
|
720
720
|
new MathFunctionMatcher(),
|
|
@@ -321,7 +321,7 @@ export class CSSModel extends SDKModel {
|
|
|
321
321
|
hasScroll,
|
|
322
322
|
};
|
|
323
323
|
}
|
|
324
|
-
async
|
|
324
|
+
async getEnvironmentVariables() {
|
|
325
325
|
const response = await this.agent.invoke_getEnvironmentVariables();
|
|
326
326
|
if (response.getError()) {
|
|
327
327
|
return {};
|
|
@@ -20,9 +20,9 @@ export class CSSProperty extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
20
20
|
implicit;
|
|
21
21
|
text;
|
|
22
22
|
range;
|
|
23
|
-
#active;
|
|
24
|
-
#nameRange;
|
|
25
|
-
#valueRange;
|
|
23
|
+
#active = true;
|
|
24
|
+
#nameRange = null;
|
|
25
|
+
#valueRange = null;
|
|
26
26
|
#invalidString;
|
|
27
27
|
#longhandProperties = [];
|
|
28
28
|
constructor(ownerStyle, index, name, value, important, disabled, parsedOk, implicit, text, range, longhandProperties) {
|
|
@@ -37,9 +37,6 @@ export class CSSProperty extends Common.ObjectWrapper.ObjectWrapper {
|
|
|
37
37
|
this.implicit = implicit; // A longhand, implicitly set by missing values of shorthand.
|
|
38
38
|
this.text = text;
|
|
39
39
|
this.range = range ? TextUtils.TextRange.TextRange.fromObject(range) : null;
|
|
40
|
-
this.#active = true;
|
|
41
|
-
this.#nameRange = null;
|
|
42
|
-
this.#valueRange = null;
|
|
43
40
|
if (longhandProperties && longhandProperties.length > 0) {
|
|
44
41
|
for (const property of longhandProperties) {
|
|
45
42
|
this.#longhandProperties.push(new CSSProperty(ownerStyle, ++index, property.name, property.value, important, disabled, parsedOk, true));
|
package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2023 The Chromium Authors
|
|
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
|
-
/* eslint-disable
|
|
4
|
+
/* eslint-disable @devtools/no-imperative-dom-api */
|
|
5
5
|
import * as Common from '../../core/common/common.js';
|
|
6
6
|
import { CSSMetadata, cssMetadata, CubicBezierKeywordValues, } from './CSSMetadata.js';
|
|
7
7
|
import { ASTUtils, matchDeclaration, matcherBase, tokenizeDeclaration } from './CSSPropertyParser.js';
|
|
@@ -993,21 +993,22 @@ export class CustomFunctionMatcher extends matcherBase(CustomFunctionMatch) {
|
|
|
993
993
|
return new CustomFunctionMatch(text, node, callee, args);
|
|
994
994
|
}
|
|
995
995
|
}
|
|
996
|
-
export class
|
|
996
|
+
export class FlexGridMasonryMatch {
|
|
997
997
|
text;
|
|
998
998
|
node;
|
|
999
|
-
|
|
1000
|
-
constructor(text, node,
|
|
999
|
+
layoutType;
|
|
1000
|
+
constructor(text, node, layoutType) {
|
|
1001
1001
|
this.text = text;
|
|
1002
1002
|
this.node = node;
|
|
1003
|
-
this.
|
|
1003
|
+
this.layoutType = layoutType;
|
|
1004
1004
|
}
|
|
1005
1005
|
}
|
|
1006
1006
|
// clang-format off
|
|
1007
|
-
export class
|
|
1007
|
+
export class FlexGridMasonryMatcher extends matcherBase(FlexGridMasonryMatch) {
|
|
1008
1008
|
// clang-format on
|
|
1009
1009
|
static FLEX = ['flex', 'inline-flex', 'block flex', 'inline flex'];
|
|
1010
1010
|
static GRID = ['grid', 'inline-grid', 'block grid', 'inline grid'];
|
|
1011
|
+
static MASONRY = ['masonry', 'inline-masonry', 'block masonry', 'inline masonry'];
|
|
1011
1012
|
accepts(propertyName) {
|
|
1012
1013
|
return propertyName === 'display';
|
|
1013
1014
|
}
|
|
@@ -1023,11 +1024,14 @@ export class FlexGridMatcher extends matcherBase(FlexGridMatch) {
|
|
|
1023
1024
|
.map(node => matching.getComputedText(node).trim())
|
|
1024
1025
|
.filter(value => value);
|
|
1025
1026
|
const text = values.join(' ');
|
|
1026
|
-
if (
|
|
1027
|
-
return new
|
|
1027
|
+
if (FlexGridMasonryMatcher.FLEX.includes(text)) {
|
|
1028
|
+
return new FlexGridMasonryMatch(matching.ast.text(node), node, "flex" /* LayoutType.FLEX */);
|
|
1028
1029
|
}
|
|
1029
|
-
if (
|
|
1030
|
-
return new
|
|
1030
|
+
if (FlexGridMasonryMatcher.GRID.includes(text)) {
|
|
1031
|
+
return new FlexGridMasonryMatch(matching.ast.text(node), node, "grid" /* LayoutType.GRID */);
|
|
1032
|
+
}
|
|
1033
|
+
if (FlexGridMasonryMatcher.MASONRY.includes(text)) {
|
|
1034
|
+
return new FlexGridMasonryMatch(matching.ast.text(node), node, "masonry" /* LayoutType.MASONRY */);
|
|
1031
1035
|
}
|
|
1032
1036
|
return null;
|
|
1033
1037
|
}
|
package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStyleDeclaration.js
CHANGED
|
@@ -7,14 +7,14 @@ import { CSSProperty } from './CSSProperty.js';
|
|
|
7
7
|
export class CSSStyleDeclaration {
|
|
8
8
|
#cssModel;
|
|
9
9
|
parentRule;
|
|
10
|
-
#allProperties;
|
|
10
|
+
#allProperties = [];
|
|
11
11
|
styleSheetId;
|
|
12
|
-
range;
|
|
12
|
+
range = null;
|
|
13
13
|
cssText;
|
|
14
14
|
#shorthandValues = new Map();
|
|
15
15
|
#shorthandIsImportant = new Set();
|
|
16
16
|
#activePropertyMap = new Map();
|
|
17
|
-
#leadingProperties;
|
|
17
|
+
#leadingProperties = null;
|
|
18
18
|
type;
|
|
19
19
|
// For CSSStyles coming from animations,
|
|
20
20
|
// This holds the name of the animation.
|
|
@@ -82,7 +82,7 @@ export class CSSStyleDeclaration {
|
|
|
82
82
|
this.#generateSyntheticPropertiesIfNeeded();
|
|
83
83
|
this.#computeInactiveProperties();
|
|
84
84
|
// TODO(changhaohan): verify if this #activePropertyMap is still necessary, or if it is
|
|
85
|
-
// providing different information against the activeness in
|
|
85
|
+
// providing different information against the activeness in #allProperties.
|
|
86
86
|
this.#activePropertyMap = new Map();
|
|
87
87
|
for (const property of this.#allProperties) {
|
|
88
88
|
if (!property.activeInStyle()) {
|
package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
5
5
|
import * as Common from '../common/common.js';
|
|
6
6
|
import * as Host from '../host/host.js';
|
|
7
|
-
import { ParallelConnection } from './Connections.js';
|
|
8
7
|
import { ResourceTreeModel } from './ResourceTreeModel.js';
|
|
9
8
|
import { SDKModel } from './SDKModel.js';
|
|
10
9
|
import { SecurityOriginManager } from './SecurityOriginManager.js';
|
|
@@ -29,7 +28,6 @@ export class ChildTargetManager extends SDKModel {
|
|
|
29
28
|
#targetInfos = new Map();
|
|
30
29
|
#childTargetsBySessionId = new Map();
|
|
31
30
|
#childTargetsById = new Map();
|
|
32
|
-
#parallelConnections = new Map();
|
|
33
31
|
#parentTargetId = null;
|
|
34
32
|
constructor(parentTarget) {
|
|
35
33
|
super(parentTarget);
|
|
@@ -221,42 +219,16 @@ export class ChildTargetManager extends SDKModel {
|
|
|
221
219
|
}
|
|
222
220
|
}
|
|
223
221
|
detachedFromTarget({ sessionId }) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (target) {
|
|
230
|
-
target.dispose('target terminated');
|
|
231
|
-
this.#childTargetsBySessionId.delete(sessionId);
|
|
232
|
-
this.#childTargetsById.delete(target.id());
|
|
233
|
-
}
|
|
222
|
+
const target = this.#childTargetsBySessionId.get(sessionId);
|
|
223
|
+
if (target) {
|
|
224
|
+
target.dispose('target terminated');
|
|
225
|
+
this.#childTargetsBySessionId.delete(sessionId);
|
|
226
|
+
this.#childTargetsById.delete(target.id());
|
|
234
227
|
}
|
|
235
228
|
}
|
|
236
229
|
receivedMessageFromTarget({}) {
|
|
237
230
|
// We use flatten protocol.
|
|
238
231
|
}
|
|
239
|
-
async createParallelConnection(onMessage) {
|
|
240
|
-
// The main Target id is actually just `main`, instead of the real targetId.
|
|
241
|
-
// Get the real id (requires an async operation) so that it can be used synchronously later.
|
|
242
|
-
const targetId = await this.getParentTargetId();
|
|
243
|
-
const { connection, sessionId } = await this.createParallelConnectionAndSessionForTarget(this.#parentTarget, targetId);
|
|
244
|
-
connection.setOnMessage(onMessage);
|
|
245
|
-
this.#parallelConnections.set(sessionId, connection);
|
|
246
|
-
return { connection, sessionId };
|
|
247
|
-
}
|
|
248
|
-
async createParallelConnectionAndSessionForTarget(target, targetId) {
|
|
249
|
-
const targetAgent = target.targetAgent();
|
|
250
|
-
const targetRouter = target.router();
|
|
251
|
-
const sessionId = (await targetAgent.invoke_attachToTarget({ targetId, flatten: true })).sessionId;
|
|
252
|
-
const connection = new ParallelConnection(targetRouter.connection(), sessionId);
|
|
253
|
-
targetRouter.registerSession(target, sessionId, connection);
|
|
254
|
-
connection.setOnDisconnect(() => {
|
|
255
|
-
targetRouter.unregisterSession(sessionId);
|
|
256
|
-
void targetAgent.invoke_detachFromTarget({ sessionId });
|
|
257
|
-
});
|
|
258
|
-
return { connection, sessionId };
|
|
259
|
-
}
|
|
260
232
|
targetInfos() {
|
|
261
233
|
return Array.from(this.#targetInfos.values());
|
|
262
234
|
}
|