chrome-devtools-frontend 1.0.1660788 → 1.0.1662289
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/.agents/skills/evaluate-ai-css-completion/SKILL.md +143 -0
- package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +104 -0
- package/.agents/skills/migrate-chromium-test/SKILL.md +7 -2
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
- package/docs/ui_engineering.md +75 -42
- package/eslint.config.mjs +7 -0
- package/extension-api/ExtensionAPI.d.ts +88 -0
- package/front_end/core/common/SettingRegistration.ts +0 -5
- package/front_end/core/host/InspectorFrontendHost.ts +1 -0
- package/front_end/core/host/InspectorFrontendHostStub.ts +2 -0
- package/front_end/core/platform/ArrayUtilities.ts +10 -0
- package/front_end/core/platform/StringUtilities.ts +20 -4
- package/front_end/core/sdk/CPUThrottlingManager.ts +2 -0
- package/front_end/core/sdk/DOMDebuggerModel.ts +2 -0
- package/front_end/core/sdk/DOMModel.ts +1 -0
- package/front_end/core/sdk/DebuggerModel.ts +4 -4
- package/front_end/core/sdk/EventBreakpointsModel.ts +2 -0
- package/front_end/core/sdk/FrameManager.ts +1 -0
- package/front_end/core/sdk/IsolateManager.ts +1 -0
- package/front_end/core/sdk/NetworkManager.ts +2 -0
- package/front_end/core/sdk/NetworkRequest.ts +1 -0
- package/front_end/core/sdk/PageResourceLoader.ts +2 -0
- package/front_end/core/sdk/SourceMap.ts +5 -5
- package/front_end/core/sdk/SourceMapManager.ts +3 -2
- package/front_end/core/sdk/TargetManager.ts +4 -0
- package/front_end/entrypoints/main/MainImpl.ts +2 -1
- package/front_end/foundation/README.md +86 -0
- package/front_end/generated/InspectorBackendCommands.ts +4 -5
- package/front_end/generated/protocol.ts +20 -38
- package/front_end/models/bindings/CompilerScriptMapping.ts +5 -5
- package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +3 -3
- package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
- package/front_end/models/bindings/ResourceMapping.ts +3 -3
- package/front_end/models/bindings/ResourceScriptMapping.ts +2 -2
- package/front_end/models/bindings/SASSSourceMapping.ts +3 -3
- package/front_end/models/bindings/TempFile.ts +8 -3
- package/front_end/models/extensions/ExtensionAPI.ts +110 -46
- package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
- package/front_end/models/formatter/ScriptFormatter.ts +8 -11
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +14 -5
- package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +8 -9
- package/front_end/models/issues_manager/CookieIssue.ts +21 -9
- package/front_end/models/issues_manager/Issue.ts +3 -4
- package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
- package/front_end/models/issues_manager/IssueResolver.ts +2 -2
- package/front_end/models/issues_manager/IssuesManager.ts +136 -137
- package/front_end/models/issues_manager/RelatedIssue.ts +10 -8
- package/front_end/models/issues_manager/issues_manager.ts +0 -2
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/logs/RequestResolver.ts +2 -2
- package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -9
- package/front_end/models/trace/handlers/FramesHandler.ts +4 -7
- package/front_end/models/trace/handlers/ModelHandlers.ts +0 -1
- package/front_end/models/trace/handlers/RendererHandler.ts +2 -15
- package/front_end/models/trace/handlers/Threads.ts +4 -11
- package/front_end/models/trace/insights/DOMSize.ts +1 -1
- package/front_end/models/workspace_diff/WorkspaceDiff.ts +10 -4
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +2 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -44
- package/front_end/panels/application/CookieItemsView.ts +1 -1
- package/front_end/panels/application/ServiceWorkersView.ts +494 -411
- package/front_end/panels/application/WebMCPView.ts +38 -43
- package/front_end/panels/application/application.ts +0 -6
- package/front_end/panels/application/components/AdsView.ts +201 -30
- package/front_end/panels/application/components/adsView.css +25 -0
- package/front_end/panels/application/components/components.ts +0 -2
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +1 -1
- package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -2
- package/front_end/panels/application/serviceWorkersView.css +40 -4
- package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +147 -123
- package/front_end/panels/common/ExtensionServer.ts +3 -3
- package/front_end/panels/console/ConsoleView.ts +3 -2
- package/front_end/panels/console/PromptBuilder.ts +2 -1
- package/front_end/panels/emulation/DeviceModeView.ts +164 -113
- package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
- package/front_end/panels/issues/IssueView.ts +0 -2
- package/front_end/panels/issues/IssuesPane.ts +1 -8
- package/front_end/panels/js_timeline/js_timeline-meta.ts +3 -2
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +53 -12
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +3 -3
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +5 -5
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +4 -4
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +2 -2
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryNavigator.ts +6 -6
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +3 -3
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +8 -9
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplayUtils.ts +2 -2
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
- package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +2 -2
- package/front_end/panels/network/RequestPayloadView.ts +92 -52
- package/front_end/panels/network/RequestTimingView.ts +95 -127
- package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
- package/front_end/panels/profiler/HeapSnapshotView.ts +3 -3
- package/front_end/panels/profiler/WritableProfileHeader.ts +2 -2
- package/front_end/panels/recorder/{components/ControlButton.ts → ControlButton.ts} +9 -10
- package/front_end/panels/recorder/{components/CreateRecordingView.ts → CreateRecordingView.ts} +48 -47
- package/front_end/panels/recorder/{components/ExtensionView.ts → ExtensionView.ts} +8 -8
- package/front_end/panels/recorder/RecorderController.ts +302 -127
- package/front_end/panels/recorder/RecorderPanel.ts +1 -1
- package/front_end/panels/recorder/{components/RecordingListView.ts → RecordingListView.ts} +19 -20
- package/front_end/panels/recorder/{components/RecordingView.ts → RecordingView.ts} +88 -88
- package/front_end/panels/recorder/{components/ReplaySection.ts → ReplaySection.ts} +11 -11
- package/front_end/panels/recorder/{components/SelectorPicker.ts → SelectorPicker.ts} +13 -13
- package/front_end/panels/recorder/{components/StepEditor.ts → StepEditor.ts} +15 -15
- package/front_end/panels/recorder/{components/StepView.ts → StepView.ts} +10 -10
- package/front_end/panels/recorder/{components/TimelineSection.ts → TimelineSection.ts} +2 -2
- package/front_end/panels/recorder/recorder.ts +23 -1
- package/front_end/panels/recorder/util/util.ts +113 -0
- package/front_end/panels/sources/SourcesView.ts +0 -17
- package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
- package/front_end/panels/sources/UISourceCodeFrame.ts +42 -0
- package/front_end/panels/sources/sources.ts +0 -2
- package/front_end/panels/timeline/CompatibilityTracksAppender.ts +0 -17
- package/front_end/panels/timeline/IsolateSelector.ts +10 -8
- package/front_end/panels/timeline/ThreadAppender.ts +0 -106
- package/front_end/panels/timeline/TimelinePanel.ts +18 -7
- package/front_end/panels/timeline/TimelineUIUtils.ts +144 -129
- package/front_end/panels/timeline/timeline-meta.ts +3 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/report_view/ReportView.ts +11 -5
- package/front_end/ui/components/report_view/report.css +4 -1
- package/front_end/ui/legacy/TextPrompt.ts +49 -1
- package/front_end/ui/legacy/Treeoutline.ts +3 -0
- package/front_end/ui/legacy/UIUtils.ts +11 -1
- package/front_end/ui/legacy/Widget.ts +14 -15
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +11 -7
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -1
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +10 -1
- package/front_end/ui/legacy/textPrompt.css +10 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
- package/front_end/models/issues_manager/AttributionReportingIssue.ts +0 -247
- package/front_end/models/issues_manager/descriptions/arInsecureContext.md +0 -7
- package/front_end/models/issues_manager/descriptions/arInvalidInfoHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
- package/front_end/models/issues_manager/descriptions/arNoRegisterOsSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterOsTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoWebOrOsSupport.md +0 -4
- package/front_end/models/issues_manager/descriptions/arOsSourceIgnored.md +0 -18
- package/front_end/models/issues_manager/descriptions/arOsTriggerIgnored.md +0 -19
- package/front_end/models/issues_manager/descriptions/arPermissionPolicyDisabled.md +0 -8
- package/front_end/models/issues_manager/descriptions/arSourceAndTriggerHeaders.md +0 -9
- package/front_end/models/issues_manager/descriptions/arSourceIgnored.md +0 -13
- package/front_end/models/issues_manager/descriptions/arTriggerIgnored.md +0 -12
- package/front_end/models/issues_manager/descriptions/arUntrustworthyReportingOrigin.md +0 -10
- package/front_end/models/issues_manager/descriptions/arWebAndOsHeaders.md +0 -11
- package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +0 -183
- package/front_end/panels/application/InterestGroupStorageModel.ts +0 -81
- package/front_end/panels/application/InterestGroupStorageView.ts +0 -151
- package/front_end/panels/application/InterestGroupTreeElement.ts +0 -65
- package/front_end/panels/application/components/InterestGroupAccessGrid.ts +0 -135
- package/front_end/panels/application/components/interestGroupAccessGrid.css +0 -27
- package/front_end/panels/application/interestGroupStorageView.css +0 -9
- package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +0 -182
- package/front_end/panels/recorder/components/components.ts +0 -25
- package/front_end/panels/recorder/components/util.ts +0 -116
- package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
- /package/front_end/panels/recorder/{components/controlButton.css → controlButton.css} +0 -0
- /package/front_end/panels/recorder/{components/createRecordingView.css → createRecordingView.css} +0 -0
- /package/front_end/panels/recorder/{components/extensionView.css → extensionView.css} +0 -0
- /package/front_end/panels/recorder/{components/recordingListView.css → recordingListView.css} +0 -0
- /package/front_end/panels/recorder/{components/recordingView.css → recordingView.css} +0 -0
- /package/front_end/panels/recorder/{components/replaySection.css → replaySection.css} +0 -0
- /package/front_end/panels/recorder/{components/selectorPicker.css → selectorPicker.css} +0 -0
- /package/front_end/panels/recorder/{components/startView.css → startView.css} +0 -0
- /package/front_end/panels/recorder/{components/stepEditor.css → stepEditor.css} +0 -0
- /package/front_end/panels/recorder/{components/stepView.css → stepView.css} +0 -0
- /package/front_end/panels/recorder/{components/timelineSection.css → timelineSection.css} +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: evaluate-ai-css-completion
|
|
3
|
+
description: Expose a temporary evaluation hook in DevTools and run a Puppeteer script to validate CSS code completion trigger rates.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Evaluate CSS Completion Skill
|
|
7
|
+
|
|
8
|
+
This skill allows you to temporarily expose an evaluation hook in DevTools to measure CSS code completion trigger rates using a Puppeteer script.
|
|
9
|
+
|
|
10
|
+
> [!WARNING]
|
|
11
|
+
> **NEVER commit the `devtools_app.ts` patch.** It is only for local evaluation. Always revert it before uploading your CL.
|
|
12
|
+
|
|
13
|
+
## Step 1: Apply the Temporary Patch
|
|
14
|
+
|
|
15
|
+
Modify `front_end/entrypoints/devtools_app/devtools_app.ts` to expose the global `testCssCompletion` hook.
|
|
16
|
+
|
|
17
|
+
Add the following code at the end of `front_end/entrypoints/devtools_app/devtools_app.ts`:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// --- TEMPORARY EVALUATION HOOK ---
|
|
21
|
+
// TEMPORARY PATCH - REMOVE BEFORE COMMIT
|
|
22
|
+
|
|
23
|
+
import * as Host from '../../core/host/host.js';
|
|
24
|
+
import * as AiCodeCompletion from '../../models/ai_code_completion/ai_code_completion.js';
|
|
25
|
+
|
|
26
|
+
(self as any).testCss = {
|
|
27
|
+
getCases() {
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
name: 'Generic CSS Test Case',
|
|
31
|
+
url: null,
|
|
32
|
+
prefix: 'h1 { font-s',
|
|
33
|
+
suffix: ' }',
|
|
34
|
+
},
|
|
35
|
+
// Add more test cases here
|
|
36
|
+
];
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
async evaluate(uiSourceCodeUrl: string | null, prefix: string, suffix: string, additionalFiles?: any[]) {
|
|
40
|
+
const aidaClient = new Host.AidaClient.AidaClient();
|
|
41
|
+
const completion = new AiCodeCompletion.AiCodeCompletion.AiCodeCompletion(
|
|
42
|
+
{aidaClient},
|
|
43
|
+
AiCodeCompletion.AiCodeCompletion.ContextFlavor.STYLES
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const formattedAdditionalFiles = additionalFiles?.map(f => ({
|
|
47
|
+
path: f.path || f.name,
|
|
48
|
+
content: f.content || f.text,
|
|
49
|
+
included_reason: f.included_reason ?? Host.AidaClient.Reason.RELATED_FILE,
|
|
50
|
+
}));
|
|
51
|
+
|
|
52
|
+
const result = await completion.completeCode(
|
|
53
|
+
prefix,
|
|
54
|
+
suffix,
|
|
55
|
+
prefix.length,
|
|
56
|
+
Host.AidaClient.AidaInferenceLanguage.CSS,
|
|
57
|
+
formattedAdditionalFiles
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
hasSuggestion: result.response !== null && result.response.generatedSamples.length > 0,
|
|
62
|
+
suggestions: result.response?.generatedSamples.map(s => s.generationString) ?? [],
|
|
63
|
+
injectedFiles: formattedAdditionalFiles?.map(f => f.path) ?? [],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
// ----------------------------------
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Step 2: Launch Chrome with Local DevTools
|
|
71
|
+
|
|
72
|
+
Use the `npm start` script to build DevTools, launch Chrome Canary with remote debugging, and disable watch mode (so we build manually instead).
|
|
73
|
+
|
|
74
|
+
You must specify a persistent user data directory so you can log in once and reuse the session:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm start -- --no-watch --browser=canary --remote-debugging-port=9222 --user-data-dir=/tmp/devtools-ai-evaluate-css-completion
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
> [!IMPORTANT]
|
|
81
|
+
> **Instructions for the Agent:**
|
|
82
|
+
> After launching Chrome, you MUST print the following checklist to the user and wait for their explicit confirmation before running the evaluation script:
|
|
83
|
+
> 1. Sign in to Chrome with your corporate account in the new window.
|
|
84
|
+
> 2. Open DevTools, go to **Settings** (gear icon) > **AI Innovations**, and ensure **Code Completions** is enabled.
|
|
85
|
+
> 3. Focus the DevTools window and press `Cmd + Option + I` (on macOS) or `Ctrl + Shift + I` (on Windows/Linux) to open DevTools-on-DevTools (inspecting DevTools itself). Go to the Network tab of the second DevTools instance and check the **Disable cache** checkbox. This ensures your local builds are loaded instead of cached versions when reloaded.
|
|
86
|
+
> 4. Ask the user to reply when they are ready.
|
|
87
|
+
|
|
88
|
+
## Step 3: Configure Test Cases
|
|
89
|
+
|
|
90
|
+
Before running the evaluation, configure your test cases directly in `front_end/entrypoints/devtools_app/devtools_app.ts` inside the `getCases()` method of the patch you applied in Step 1.
|
|
91
|
+
|
|
92
|
+
After modifying the test cases, manually run a build to compile the changes:
|
|
93
|
+
```bash
|
|
94
|
+
autoninja -C out/Default
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For example, to test spacing sensitivity, update the returned array:
|
|
98
|
+
```typescript
|
|
99
|
+
getCases() {
|
|
100
|
+
return [
|
|
101
|
+
{
|
|
102
|
+
name: 'With CSS Context',
|
|
103
|
+
url: null,
|
|
104
|
+
prefix: 'h1 { font-s',
|
|
105
|
+
suffix: ' }',
|
|
106
|
+
additionalFiles: [
|
|
107
|
+
{
|
|
108
|
+
path: 'other.css',
|
|
109
|
+
content: 'body { color: red; }',
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Step 4: Run the Evaluation Script
|
|
118
|
+
|
|
119
|
+
Run the Puppeteer script to execute the evaluation:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
node .agents/skills/evaluate-ai-css-completion/scripts/evaluate.js
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The script will connect to the DevTools instance, trigger completions, and output the results.
|
|
126
|
+
|
|
127
|
+
### Debugging and Diagnostics
|
|
128
|
+
|
|
129
|
+
If you get 0% trigger rate or unexpected errors, check the following:
|
|
130
|
+
|
|
131
|
+
1. **Browser Logs:** The evaluation script forwards browser console logs (prefixed with `BROWSER LOG:`). Look for these in your terminal.
|
|
132
|
+
2. **Host Config:** The script prints the DevTools `Host Config` at the start. Verify that `"devToolsAiCodeCompletionStyles": { "enabled": true }` is present.
|
|
133
|
+
3. **GCA/AIDA Logs:** The script automatically enables verbose AIDA logging. Look for `GCA request succeeded:` in the logs:
|
|
134
|
+
* If the response has `"usageMetadata": { "candidatesTokenCount": X }` (where X > 0) but the `candidates` array is missing or empty, the backend generated tokens but they were filtered out (e.g., due to safety classifiers or recitation blocks).
|
|
135
|
+
4. **Context Requirement:** The CSS model is sensitive to context. A minimal prompt like `h1 { font-s` might not trigger AIDA. Ensure your test cases have enough context in the `prefix` (e.g., several preceding CSS rules) or pass them via `additionalFiles` to simulate a larger stylesheet.
|
|
136
|
+
|
|
137
|
+
## Step 5: Revert the Patch
|
|
138
|
+
|
|
139
|
+
Once the evaluation is complete and you have recorded the results, revert the patch in `devtools_app.ts`:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
git checkout front_end/entrypoints/devtools_app/devtools_app.ts
|
|
143
|
+
```
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
/* eslint-disable no-console */
|
|
6
|
+
|
|
7
|
+
const puppeteer = require('puppeteer-core');
|
|
8
|
+
|
|
9
|
+
async function runEvaluation() {
|
|
10
|
+
console.log('Connecting to Chrome...');
|
|
11
|
+
const browser = await puppeteer.connect({browserURL: 'http://127.0.0.1:9222', defaultViewport: null});
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
console.log('Opening test page (example.com)...');
|
|
15
|
+
const testPage = await browser.newPage();
|
|
16
|
+
await testPage.goto('https://example.com');
|
|
17
|
+
|
|
18
|
+
console.log('Waiting for DevTools target...');
|
|
19
|
+
const devtoolsTarget = await browser.waitForTarget(t => {
|
|
20
|
+
return t.url().startsWith('devtools://') || t.url().includes('inspector.html');
|
|
21
|
+
}, {timeout: 10000});
|
|
22
|
+
|
|
23
|
+
console.log('Connecting to DevTools page...');
|
|
24
|
+
const devtoolsPage = await devtoolsTarget.page();
|
|
25
|
+
if (!devtoolsPage) {
|
|
26
|
+
throw new Error('Could not get DevTools page object. Make sure DevTools is undocked or opened in a tab.');
|
|
27
|
+
}
|
|
28
|
+
console.log('DevTools URL:', devtoolsPage.url());
|
|
29
|
+
|
|
30
|
+
devtoolsPage.on('console', msg => console.log('BROWSER LOG:', msg.text()));
|
|
31
|
+
|
|
32
|
+
console.log('Reloading DevTools to ensure patch is loaded...');
|
|
33
|
+
try {
|
|
34
|
+
await devtoolsPage.setCacheEnabled(false);
|
|
35
|
+
await devtoolsPage.reload({waitUntil: 'domcontentloaded', timeout: 10000});
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.log('Reload warning (proceeding anyway):', e.message);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await devtoolsPage.evaluate(() => localStorage.setItem('debugAiCodeCompletionEnabled', 'true'));
|
|
41
|
+
await devtoolsPage.evaluate(() => localStorage.setItem('debugAiServicesEnabled', 'true'));
|
|
42
|
+
await devtoolsPage.evaluate(() => localStorage.setItem('debugAiAssistancePanelEnabled', 'true'));
|
|
43
|
+
await devtoolsPage.evaluate(() => localStorage.setItem('aiAssistanceStructuredLogEnabled', 'true'));
|
|
44
|
+
|
|
45
|
+
console.log('Waiting for DevTools to initialize and hook to be available...');
|
|
46
|
+
try {
|
|
47
|
+
await devtoolsPage.waitForFunction(() => typeof self.testCss?.getCases === 'function', {timeout: 15000});
|
|
48
|
+
} catch {
|
|
49
|
+
throw new Error('testCss.getCases hook not found. Did you apply the patch and build? Is this the local build?');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log('Fetching test cases from DevTools...');
|
|
53
|
+
const hostConfig = await devtoolsPage.evaluate(() => self.testCss.getHostConfig());
|
|
54
|
+
console.log('Host Config:', JSON.stringify(hostConfig, null, 2));
|
|
55
|
+
const testCases = await devtoolsPage.evaluate(() => self.testCss.getCases());
|
|
56
|
+
console.log(`Found ${testCases.length} test cases. Running each case 5 times.`);
|
|
57
|
+
|
|
58
|
+
let totalQueries = 0;
|
|
59
|
+
for (const tc of testCases) {
|
|
60
|
+
console.log(`\nRunning: ${tc.name}`);
|
|
61
|
+
let successCount = 0;
|
|
62
|
+
const suggestions = new Set();
|
|
63
|
+
|
|
64
|
+
for (let run = 1; run <= 5; run++) {
|
|
65
|
+
// Delay to avoid rate limiting
|
|
66
|
+
await new Promise(resolve => setTimeout(resolve, 1200));
|
|
67
|
+
try {
|
|
68
|
+
const result = await devtoolsPage.evaluate(async (url, prefix, suffix, additionalFiles) => {
|
|
69
|
+
return await self.testCss.evaluate(url, prefix, suffix, additionalFiles);
|
|
70
|
+
}, tc.url, tc.prefix, tc.suffix, tc.additionalFiles);
|
|
71
|
+
|
|
72
|
+
if (result.hasSuggestion) {
|
|
73
|
+
successCount++;
|
|
74
|
+
for (const s of result.suggestions) {
|
|
75
|
+
suggestions.add(s);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.error(` [Run ${run}] Failed:`, e.message);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
totalQueries++;
|
|
83
|
+
if (totalQueries % 20 === 0) {
|
|
84
|
+
console.log('[INFO] Pausing for 8 seconds to prevent rate limiting...');
|
|
85
|
+
await new Promise(resolve => setTimeout(resolve, 8000));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(` Result: [Success Rate: ${successCount}/5]`);
|
|
90
|
+
if (suggestions.size > 0) {
|
|
91
|
+
console.log(' Unique Suggestions:', Array.from(suggestions));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Cleanup tabs
|
|
96
|
+
await devtoolsPage.close();
|
|
97
|
+
await testPage.close();
|
|
98
|
+
} finally {
|
|
99
|
+
console.log('Disconnecting from Chrome...');
|
|
100
|
+
await browser.disconnect();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
runEvaluation().catch(console.error);
|
|
@@ -24,6 +24,8 @@ description: Use when migrating Chromium layout tests to DevTools unit tests
|
|
|
24
24
|
- If the test requires rendering, use `renderElementIntoDOM` to attach elements to a test container.
|
|
25
25
|
- If testing legacy components that require internal tokens or have private methods, try to use public APIs or events instead. If impossible, consider using structural typing workarounds or updating the component to be more testable.
|
|
26
26
|
- If tests require a repetitive setup extract it into a test helper function at the top of the file.
|
|
27
|
+
- Code comments must be full sentences ending with a period, except when the entire comment is a URL.
|
|
28
|
+
- Do not include comments of the form `// Replaces web test: http/tests/devtools/persistence/automapping-absolute-paths.js`. Since we plan to remove migrated web tests, these are not useful references.
|
|
27
29
|
|
|
28
30
|
4. **Update BUILD.gn**:
|
|
29
31
|
|
|
@@ -40,7 +42,10 @@ description: Use when migrating Chromium layout tests to DevTools unit tests
|
|
|
40
42
|
- If the newly added test does not test any logic from the component but just the getters from the mocked data explain to the user that this test does not add value and it's better to close it without adding the test. Provide a command without executing it to close the issue as "Fixed".
|
|
41
43
|
- If the newly added test uses too extensive mocks of CDP objects and methods explain to the user that the test should be foundation e2e test instead of unit test and we won't migrate it. Provide a command without executing it to close the issue as "Won't Fix (Infeasible)".
|
|
42
44
|
|
|
43
|
-
7.
|
|
45
|
+
7. Uploading a CL with your changes using the `version-control` skill. And **STRICTLY** follow the following additional template
|
|
46
|
+
- **Title**: `[test-migration] Migrating <chromium-test-name> to unit test`
|
|
47
|
+
- **Body**: `Migrated <link-to-chromium-test> to <devtools-test-name>`
|
|
48
|
+
- **Footer**: Use `Fixed: <issue number>` trailer instead of `Bug: <issue number>`.
|
|
44
49
|
|
|
45
50
|
## Example Conversion
|
|
46
51
|
|
|
@@ -69,7 +74,7 @@ import {describeWithEnvironment} from '../../../../testing/EnvironmentHelpers.js
|
|
|
69
74
|
describeWithEnvironment('DataGrid', () => {
|
|
70
75
|
it('tests long text in datagrid', () => {
|
|
71
76
|
// ... setup grid ...
|
|
72
|
-
// Use assertions instead of printing results
|
|
77
|
+
// Use assertions instead of printing results.
|
|
73
78
|
assert.strictEqual(keyElement.textContent.length, 1500);
|
|
74
79
|
});
|
|
75
80
|
});
|
|
@@ -110,7 +110,13 @@ existing element containers.
|
|
|
110
110
|
* The Gerrit Code Review UI cannot identify moved blocks of unchanged code.
|
|
111
111
|
* If blocks of code need to be reordered, create a "prefactoring" change that first extracts the code that needs to be reordered into a named helper functions and pause the migration, waiting user confirmation.
|
|
112
112
|
|
|
113
|
-
12. **
|
|
113
|
+
12. **Micro-Commit Strategy**:
|
|
114
|
+
|
|
115
|
+
* Do not attempt to convert every helper method and UI component in a single monolithic commit. Break the template extraction into **small, self-contained micro-commits** (e.g., migrating one helper method, toolbar button, or list item render at a time).
|
|
116
|
+
* Verify with build and run tests after each micro-commit to guarantee zero regressions and 100% visual parity before moving to the next compartment.
|
|
117
|
+
* Provide the exact list of files and commit message when presenting progress so the change history remains atomic and easy to review.
|
|
118
|
+
|
|
119
|
+
13. **Wait for confirmation**:
|
|
114
120
|
|
|
115
121
|
* Wait for an explicit confirmation from the user before proceeding to the
|
|
116
122
|
next step.
|
package/docs/ui_engineering.md
CHANGED
|
@@ -222,25 +222,38 @@ This section provides a series of examples for migrating from imperative DOM man
|
|
|
222
222
|
|
|
223
223
|
## Setting `className` on `this.element`
|
|
224
224
|
|
|
225
|
-
Instead of setting `className` directly on `this.element`, define the component's structure declaratively using a lit-html template.
|
|
225
|
+
Instead of setting `className` directly on `this.element`, define the component's structure declaratively using a lit-html template. When classes or attributes (`jslog`) must be set directly on `target` itself (for example when `target` is positioned externally via `.positionAt()`), use the `container` option in DevTools' custom `render()` (`front_end/ui/lit/render.ts`).
|
|
226
226
|
|
|
227
227
|
**Before:**
|
|
228
228
|
```typescript
|
|
229
229
|
class SomeWidget extends UI.Widget.Widget {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
230
|
+
constructor(element?: HTMLElement) {
|
|
231
|
+
super(element, {jslog: `${VisualLogging.deviceModeRuler().track({click: true})}`});
|
|
232
|
+
this.element.className = 'some-class';
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
235
|
```
|
|
236
236
|
|
|
237
|
-
**After:**
|
|
237
|
+
**After (when creating an inner wrapper):**
|
|
238
238
|
```typescript
|
|
239
|
-
|
|
240
239
|
export const DEFAULT_VIEW = (input, _output, target) => {
|
|
241
240
|
render(html`
|
|
242
241
|
<div class="some-class"></div>`,
|
|
243
|
-
target
|
|
242
|
+
target);
|
|
243
|
+
};
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**After (when classes or attributes must be applied directly to `target` itself):**
|
|
247
|
+
```typescript
|
|
248
|
+
export const DEFAULT_VIEW = (input, _output, target) => {
|
|
249
|
+
render(html`
|
|
250
|
+
<div class="some-content">...</div>`,
|
|
251
|
+
target, {
|
|
252
|
+
container: {
|
|
253
|
+
classes: ['some-class'],
|
|
254
|
+
attributes: {jslog: VisualLogging.deviceModeRuler().track({click: true})},
|
|
255
|
+
},
|
|
256
|
+
});
|
|
244
257
|
};
|
|
245
258
|
```
|
|
246
259
|
|
|
@@ -268,7 +281,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
268
281
|
<div>
|
|
269
282
|
<div></div>
|
|
270
283
|
</div>`,
|
|
271
|
-
target
|
|
284
|
+
target);
|
|
272
285
|
};
|
|
273
286
|
```
|
|
274
287
|
|
|
@@ -296,7 +309,7 @@ class SomeWidget extends UI.Widget.Widget {
|
|
|
296
309
|
export const DEFAULT_VIEW = (input, _output, target) => {
|
|
297
310
|
render(html`
|
|
298
311
|
<div class="some-class" aria-label="some-label">some-text</div>`,
|
|
299
|
-
target
|
|
312
|
+
target);
|
|
300
313
|
};
|
|
301
314
|
```
|
|
302
315
|
|
|
@@ -326,7 +339,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
326
339
|
<div>
|
|
327
340
|
<div class="some-class container" @click=${this.onClick.bind(this)}></div>
|
|
328
341
|
</div>`,
|
|
329
|
-
target
|
|
342
|
+
target);
|
|
330
343
|
};
|
|
331
344
|
```
|
|
332
345
|
|
|
@@ -353,7 +366,7 @@ class SomeWidget extends UI.Widget.Widget {
|
|
|
353
366
|
export const DEFAULT_VIEW = (input, _output, target) => {
|
|
354
367
|
render(html`
|
|
355
368
|
<div style="width:100%; margin-left:10px"></div>`,
|
|
356
|
-
target
|
|
369
|
+
target);
|
|
357
370
|
};
|
|
358
371
|
```
|
|
359
372
|
|
|
@@ -383,7 +396,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
383
396
|
<div>
|
|
384
397
|
<div class="some-class"></div>
|
|
385
398
|
</div>`,
|
|
386
|
-
target
|
|
399
|
+
target);
|
|
387
400
|
};
|
|
388
401
|
```
|
|
389
402
|
|
|
@@ -411,7 +424,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
411
424
|
<div>
|
|
412
425
|
<span class="some-class">some-text</span>
|
|
413
426
|
</div>`,
|
|
414
|
-
target
|
|
427
|
+
target);
|
|
415
428
|
};
|
|
416
429
|
```
|
|
417
430
|
|
|
@@ -450,7 +463,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
450
463
|
</devtools-toolbar-input>
|
|
451
464
|
</devtools-toolbar>
|
|
452
465
|
</div>`,
|
|
453
|
-
target
|
|
466
|
+
target);
|
|
454
467
|
};
|
|
455
468
|
```
|
|
456
469
|
|
|
@@ -483,7 +496,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
483
496
|
aria-label="accessible-placeholder" style="flex-grow:0.5; flex-shrink:1"></devtools-toolbar-input>
|
|
484
497
|
</devtools-toolbar>
|
|
485
498
|
</div>`,
|
|
486
|
-
target
|
|
499
|
+
target);
|
|
487
500
|
};
|
|
488
501
|
```
|
|
489
502
|
|
|
@@ -523,7 +536,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
523
536
|
<span><div style="font-size: 12px;">💫</div></span>
|
|
524
537
|
</devtools-adorner>
|
|
525
538
|
</div>`,
|
|
526
|
-
target
|
|
539
|
+
target);
|
|
527
540
|
};
|
|
528
541
|
```
|
|
529
542
|
|
|
@@ -558,7 +571,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
558
571
|
.jslogContext=${'edit-name'}></devtools-button>
|
|
559
572
|
</devtools-toolbar>
|
|
560
573
|
</div>`,
|
|
561
|
-
target
|
|
574
|
+
target);
|
|
562
575
|
};
|
|
563
576
|
```
|
|
564
577
|
|
|
@@ -618,7 +631,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
618
631
|
<input type="text" placeholder="some-placeholder" value="some-value"
|
|
619
632
|
?disabled=${!this.enabled} checked>
|
|
620
633
|
</div>`,
|
|
621
|
-
target
|
|
634
|
+
target);
|
|
622
635
|
};
|
|
623
636
|
```
|
|
624
637
|
|
|
@@ -661,7 +674,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
661
674
|
<devtools-button class="some-class" title=${i18nString(UIStrings.someTitle)} @click=${onClick}
|
|
662
675
|
.jslogContext=${'some-button'} .variant=${Buttons.Button.Variant.PRIMARY}>Some button</devtools-button>
|
|
663
676
|
</div>`,
|
|
664
|
-
target
|
|
677
|
+
target);
|
|
665
678
|
};
|
|
666
679
|
```
|
|
667
680
|
|
|
@@ -689,7 +702,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
689
702
|
<div>
|
|
690
703
|
<div class="some-class">some-text</div>
|
|
691
704
|
</div>`,
|
|
692
|
-
target
|
|
705
|
+
target);
|
|
693
706
|
};
|
|
694
707
|
```
|
|
695
708
|
|
|
@@ -760,7 +773,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
760
773
|
<devtools-icon name="checkmark"
|
|
761
774
|
style="color:var(--icon-checkmark-green); width:14px; height:14px"></devtools-icon>
|
|
762
775
|
</div>`,
|
|
763
|
-
target
|
|
776
|
+
target);
|
|
764
777
|
};
|
|
765
778
|
```
|
|
766
779
|
|
|
@@ -811,7 +824,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
811
824
|
<devtools-checkbox ${bindToSetting(this.someOtherSetting)}>${this.someOtherSetting.title()}</devtools-checkbox>
|
|
812
825
|
</devtools-toolbar>
|
|
813
826
|
</div>`,
|
|
814
|
-
target
|
|
827
|
+
target);
|
|
815
828
|
};
|
|
816
829
|
```
|
|
817
830
|
|
|
@@ -844,7 +857,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
844
857
|
<devtools-button ${bindToAction('elements.refresh-event-listeners')}></devtools-button>
|
|
845
858
|
</devtools-toolbar>
|
|
846
859
|
</div>`,
|
|
847
|
-
target
|
|
860
|
+
target);
|
|
848
861
|
};
|
|
849
862
|
```
|
|
850
863
|
|
|
@@ -878,7 +891,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
878
891
|
</devtools-checkbox>
|
|
879
892
|
</devtools-toolbar>
|
|
880
893
|
</div>`,
|
|
881
|
-
target
|
|
894
|
+
target);
|
|
882
895
|
};
|
|
883
896
|
```
|
|
884
897
|
|
|
@@ -910,7 +923,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
910
923
|
@change=${this.someToolbarComboBoxClicked.bind(this)}></select>
|
|
911
924
|
</devtools-toolbar>
|
|
912
925
|
</div>`,
|
|
913
|
-
target
|
|
926
|
+
target);
|
|
914
927
|
};
|
|
915
928
|
```
|
|
916
929
|
|
|
@@ -970,7 +983,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
970
983
|
<div class="toolbar-spacer"></div>
|
|
971
984
|
</devtools-toolbar>
|
|
972
985
|
</div>`,
|
|
973
|
-
target
|
|
986
|
+
target);
|
|
974
987
|
};
|
|
975
988
|
```
|
|
976
989
|
|
|
@@ -1001,7 +1014,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1001
1014
|
<div>
|
|
1002
1015
|
<iframe sandbox tabindex="-1"></iframe>
|
|
1003
1016
|
</div>`,
|
|
1004
|
-
target
|
|
1017
|
+
target);
|
|
1005
1018
|
};
|
|
1006
1019
|
```
|
|
1007
1020
|
|
|
@@ -1030,7 +1043,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1030
1043
|
<input class="harmony-input add-source-map" spellcheck="false" type="text"
|
|
1031
1044
|
jslog=${VisualLogging.textField('url').track({keydown: 'Enter', change: true})}>
|
|
1032
1045
|
</div>`,
|
|
1033
|
-
target
|
|
1046
|
+
target);
|
|
1034
1047
|
};
|
|
1035
1048
|
```
|
|
1036
1049
|
|
|
@@ -1098,7 +1111,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1098
1111
|
</table>
|
|
1099
1112
|
</devtools-data-grid>
|
|
1100
1113
|
</div>`,
|
|
1101
|
-
target
|
|
1114
|
+
target);
|
|
1102
1115
|
};
|
|
1103
1116
|
```
|
|
1104
1117
|
|
|
@@ -1182,7 +1195,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1182
1195
|
</devtools-split-view>
|
|
1183
1196
|
</devtools-split-view>
|
|
1184
1197
|
</div>`,
|
|
1185
|
-
target
|
|
1198
|
+
target);
|
|
1186
1199
|
};
|
|
1187
1200
|
```
|
|
1188
1201
|
|
|
@@ -1233,7 +1246,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1233
1246
|
<div role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0.5"
|
|
1234
1247
|
aria-valuetext="50% done"></div>
|
|
1235
1248
|
</div>`,
|
|
1236
|
-
target
|
|
1249
|
+
target);
|
|
1237
1250
|
};
|
|
1238
1251
|
```
|
|
1239
1252
|
|
|
@@ -1265,15 +1278,20 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1265
1278
|
header: i18nString(UIStrings.nothingToSeeHere), text: this.explanation,
|
|
1266
1279
|
link: 'http://www.google.com',})}
|
|
1267
1280
|
</div>`,
|
|
1268
|
-
target
|
|
1281
|
+
target);
|
|
1269
1282
|
};
|
|
1270
1283
|
```
|
|
1271
1284
|
|
|
1272
|
-
## Migrating `TextPrompt`
|
|
1285
|
+
## Migrating `TextPrompt` and `InplaceEditor`
|
|
1273
1286
|
|
|
1274
|
-
Replace imperative `TextPrompt` creation with the declarative `<devtools-prompt>` component, providing completions via `<datalist>`.
|
|
1287
|
+
Replace imperative `TextPrompt` or `UI.InplaceEditor` creation with the declarative `<devtools-prompt>` component, providing completions via `<datalist>`.
|
|
1275
1288
|
|
|
1276
|
-
|
|
1289
|
+
### Critical Rules for `<devtools-prompt>`:
|
|
1290
|
+
1. **Prompt Owns the Content (`<slot>`)**: When `editing` is `false`, `<devtools-prompt>` renders `<span class="entrypoint"><slot></slot></span>` in shadow DOM. Therefore, `<devtools-prompt>` **must contain the display text/title directly as a child** (`<devtools-prompt ...>${title}</devtools-prompt>`) and live inside the element container (e.g., inside `<devtools-checkbox>`).
|
|
1291
|
+
2. **Do Not Conditionally Swap Elements**: Do NOT render `<devtools-prompt>` conditionally *in place of* a `<span>` or text node (`isEditing ? html`<devtools-prompt>...` : html`<span>${title}</span>``). Mount `<devtools-prompt>` unconditionally, holding the text content at all times, and only toggle its boolean property `?editing=${item === input.editingItem}`.
|
|
1292
|
+
3. **Conditional Input Styling**: Because `<devtools-prompt>` is present in both display and editing modes, any input-mode borders or background classes must be applied conditionally (e.g., `class=${Directives.classMap({'condition-input': isEditing})}`) so non-editing rows remain unbordered.
|
|
1293
|
+
|
|
1294
|
+
**Before (`InplaceEditor` or imperative `TextPrompt`):**
|
|
1277
1295
|
```typescript
|
|
1278
1296
|
class SomeWidget extends UI.Widget.Widget {
|
|
1279
1297
|
constructor() {
|
|
@@ -1286,10 +1304,15 @@ class SomeWidget extends UI.Widget.Widget {
|
|
|
1286
1304
|
const promptElement = this.contentElement.createChild('span');
|
|
1287
1305
|
prompt.attach(promptElement);
|
|
1288
1306
|
}
|
|
1307
|
+
|
|
1308
|
+
#startEditing(item: string, element: HTMLElement): void {
|
|
1309
|
+
const config = new UI.InplaceEditor.Config(this.#commit.bind(this), this.#cancel.bind(this), element);
|
|
1310
|
+
UI.InplaceEditor.InplaceEditor.startEditing(element, config);
|
|
1311
|
+
}
|
|
1289
1312
|
}
|
|
1290
1313
|
```
|
|
1291
1314
|
|
|
1292
|
-
**After:**
|
|
1315
|
+
**After (Declarative `<devtools-prompt>` inside Lit):**
|
|
1293
1316
|
```typescript
|
|
1294
1317
|
export const DEFAULT_VIEW = (input, _output, target) => {
|
|
1295
1318
|
render(html`
|
|
@@ -1298,9 +1321,19 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1298
1321
|
<option>completion1</option>
|
|
1299
1322
|
<option>completion2</option>
|
|
1300
1323
|
</datalist>
|
|
1301
|
-
<devtools-
|
|
1324
|
+
<devtools-checkbox .checked=${input.enabled}>
|
|
1325
|
+
<devtools-prompt
|
|
1326
|
+
value=${input.item}
|
|
1327
|
+
completions="my-completions"
|
|
1328
|
+
?editing=${input.item === input.editingItem}
|
|
1329
|
+
class=${Directives.classMap({'prompt-editing-border': input.item === input.editingItem})}
|
|
1330
|
+
@commit=${(e: CustomEvent) => input.onCommit(input.item, e.detail)}
|
|
1331
|
+
@cancel=${() => input.onCancel(input.item)}>
|
|
1332
|
+
${input.title}
|
|
1333
|
+
</devtools-prompt>
|
|
1334
|
+
</devtools-checkbox>
|
|
1302
1335
|
</div>`,
|
|
1303
|
-
target
|
|
1336
|
+
target);
|
|
1304
1337
|
};
|
|
1305
1338
|
```
|
|
1306
1339
|
|
|
@@ -1346,7 +1379,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1346
1379
|
</ul>
|
|
1347
1380
|
`}></devtools-tree>
|
|
1348
1381
|
</div>`,
|
|
1349
|
-
target
|
|
1382
|
+
target);
|
|
1350
1383
|
};
|
|
1351
1384
|
```
|
|
1352
1385
|
|
|
@@ -1372,7 +1405,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
|
|
|
1372
1405
|
</ul>
|
|
1373
1406
|
`}></devtools-tree>
|
|
1374
1407
|
</div>`,
|
|
1375
|
-
target
|
|
1408
|
+
target);
|
|
1376
1409
|
};
|
|
1377
1410
|
```
|
|
1378
1411
|
|
package/eslint.config.mjs
CHANGED
|
@@ -691,6 +691,13 @@ export default defineConfig([
|
|
|
691
691
|
'lit/quoted-expressions': ['error', 'never'],
|
|
692
692
|
},
|
|
693
693
|
},
|
|
694
|
+
{
|
|
695
|
+
name: 'Front-end core files',
|
|
696
|
+
files: ['front_end/core/**/*.ts'],
|
|
697
|
+
rules: {
|
|
698
|
+
'@devtools/no-instance-of-migrated-singletons': 'error',
|
|
699
|
+
},
|
|
700
|
+
},
|
|
694
701
|
{
|
|
695
702
|
name: 'Front-end meta files',
|
|
696
703
|
files: ['front_end/**/*-meta.ts'],
|