Skip to content

Commit 08bb85b

Browse files
committed
Sync fork with chromium/7827
2 parents 950f4a8 + 33c2f40 commit 08bb85b

20,150 files changed

Lines changed: 1885795 additions & 1350106 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/OWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
file://config/owner/COMMON_OWNERS

.agents/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# .agents
2+
3+
This directory contains workspace-specific agent expertise and skills.
4+
5+
## Skills
6+
7+
Workspace skills are located in `.agents/skills/`. These represent on-demand expertise that the AI agent can activate to complete specialized tasks.
8+
9+
To use a skill, the agent will autonomously identify it based on its description and pull in the instructions using the `activate_skill` tool.
10+
11+
## Contributing
12+
13+
Contributions to existing skills or adding new ones are encouraged via CLs.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
```
2+
---
3+
name: devtools-model-management
4+
description: Guidelines for creating, migrating, and registering models in front_end/models/. Covers BUILD.gn, devtools_grd_files.gni, and entrypoints.
5+
---
6+
7+
# Creating or Migrating a Model in DevTools
8+
9+
This guide outlines the standard procedure for creating a new model or migrating an existing one to `front_end/models/`.
10+
11+
## 0. Preparation (Before you start)
12+
* **Baseline:** Run existing tests for the code you are moving to ensure they pass *before* you touch anything.
13+
* `npm run test -- front_end/<old_location>`
14+
* **Impact Analysis:** Search for usages of the class/file to understand the scope of refactoring.
15+
* `grep -r "ClassName" front_end/`
16+
17+
## 1. File Structure
18+
* **Location:** `front_end/models/<model_name>/` (must be lowercase).
19+
* **Entrypoint:** Create a barrel file `front_end/models/<model_name>/<model_name>.ts` that exports the model's public API.
20+
* **Implementation:** The actual logic goes in `<ClassName>.ts`.
21+
* **Tests:** Unit tests go in `<ClassName>.test.ts` alongside the implementation.
22+
23+
## 2. Build Configuration (`BUILD.gn`)
24+
Every model requires a `BUILD.gn` file in its directory with three specific targets:
25+
26+
1. **`devtools_module("<model_name>")`**: Lists implementation source files (`sources`) and dependencies (`deps`).
27+
* **Crucial:** Do NOT include the barrel file (`<model_name>.ts`) in `sources`.
28+
2. **`devtools_entrypoint("bundle")`**: Defines the barrel file (`entrypoint = "<model_name>.ts"`).
29+
* **Crucial:** Must depend on the module target: `deps = [ ":<model_name>" ]`.
30+
3. **`ts_library("unittests")`**: Lists test files and test-only dependencies.
31+
* **Crucial:** Must depend on the bundle: `deps = [ ":bundle" ]`.
32+
33+
## 3. Global Registration (Crucial)
34+
The build system does not auto-detect new modules. You must manually register them in **`config/gni/devtools_grd_files.gni`**:
35+
36+
* **Bundled (Release) Build:** Add the new barrel file path (e.g., `front_end/models/<model_name>/<model_name>.js`) to the `grd_files_bundled_sources` list.
37+
* **Unbundled (Debug) Build:** Add all other implementation files (e.g., `front_end/models/<model_name>/<ClassName>.js`) to the `grd_files_unbundled_sources` list.
38+
* **Test Runner:** Add the new model's unittest target (e.g., `models/<model_name>:unittests`) to the `deps` list in **`front_end/BUILD.gn`**.
39+
40+
## 4. Refactoring Imports & Exports
41+
* **Consumers:** Update all files importing the model to use the new entrypoint:
42+
`import * as ModelName from '../../models/<model_name>/<model_name>.js';`
43+
* **Old Barrel File (Migration only):** If moving a file, **remove** its export from the original directory's barrel file (e.g., `front_end/panels/elements/elements.ts`).
44+
* **Internal Imports:** Files *within* the model directory must import each other via relative paths (e.g., `./OtherClass.js`), **never** via the model's own barrel file.
45+
46+
## 5. Verification Checklist
47+
1. **Build:** `autoninja -C out/Default` (Ensures BUILD.gn and GRD files are correct).
48+
2. **Lint:** `npm run lint` (Checks style and formatting).
49+
3. **Test:**
50+
* `npm run test -- front_end/models/<model_name>` (New tests).
51+
* `npm run test -- front_end/<old_location>` (Regression check for previous owner).
52+
53+
## Common Pitfalls
54+
* **Circular Dependencies:** Occur when internal files import from the directory's own barrel file.
55+
* **Missing Tests:** Failing to add the target to `front_end/BUILD.gn` means tests exist but never run.
56+
* **Legacy Exports:** Forgetting to remove the class from the old location's `files` or `exports` allows old patterns to persist.
57+
* **Build Errors:** Including the barrel file in `devtools_module` sources causes duplicate definition errors.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
name: devtools-imports
3+
description: Conventions for importing code in Devtools to avoid build errors. Covers cross-module imports, internal imports, and the "import * as" requirement.
4+
---
5+
6+
# Imports
7+
8+
This codebase follows a special convention for importing code that must be followed to avoid build errors.
9+
10+
In DevTools each folder of code is considered a *module*:
11+
12+
- `front_end/models/trace` is the *trace module*.
13+
- `front_end/panels/timeline` is the *timeline module*.
14+
15+
Within each module there are multiple TypeScript files. *The file that is named the same as the folder name is called the entrypoint*.
16+
17+
- `front_end/models/trace/trace.ts` is the *trace module's entrypoint*
18+
- `front_end/models/trace/ModelImpl.ts` is part of the implementation of the trace module.
19+
20+
## Importing from another module
21+
22+
When you want to reuse code from other modules, *you must import that module via its entrypoint*. Imagine we are in `front_end/panels/timeline/TimelinePanel.ts`. This import is GOOD:
23+
24+
```ts
25+
import * as Trace from '../models/trace/trace.js'; // import the entrypoint
26+
```
27+
28+
This import is BAD because we import a file that is NOT the entrypoint:
29+
30+
```ts
31+
import * as ModelImpl from '../models/trace/ModelImpl.js' // NEVER ALLOWED
32+
```
33+
34+
Additionally, you **must import using the `import * as` syntax**.
35+
36+
```ts
37+
import {ModelImpl, X, Y} from '../models/trace/trace.js'; // BAD
38+
```
39+
40+
```ts
41+
import * as Trace from '../models/trace/trace.js'; // GOOD
42+
```
43+
44+
## Importing from within the same module
45+
46+
If you are within the same module, it is OK to import from files directly rather than go via the entrypoint. You can also import specifically what you need.
47+
48+
For example, if you are editing `front_end/models/trace/ModelImpl.ts` this would be acceptable:
49+
50+
```ts
51+
import {Foo} from './Foo.js'; // allowed because Foo.ts is in the same directory.
52+
```
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
---
2+
name: foundation-test-migration
3+
description: Migrating unit tests to foundation unit tests using TestUniverse and devtools_foundation_module. Use when moving tests away from DOM-heavy helpers like describeWithEnvironment or describeWithMockConnection.
4+
---
5+
6+
# Foundation Test Migration
7+
8+
This skill provides guidance on migrating DevTools unit tests to the "foundation" pattern, which is lighter, avoids global singletons, and is compatible with both Node and Browser runtimes (Isomorphic).
9+
10+
## Core Concepts
11+
12+
### devtools_foundation_module (BUILD.gn)
13+
Use this template for modules that should be platform-agnostic.
14+
- **Enforcement**: It type-checks the code against both Browser and Node APIs.
15+
- **Constraint**: Avoid direct DOM access (like `FileReader` or layout metrics) or heavy DevTools dependencies. Use `Universe` to access services.
16+
17+
### TestUniverse
18+
`TestUniverse` is the preferred way to setup a DevTools-like environment for tests without global singletons.
19+
- **Lazy**: Dependencies (targetManager, settings, workspace, etc.) are only created when accessed via getters.
20+
- **Scoped**: Does not install instances as globals (avoids `Common.Settings.Settings.instance()`).
21+
- **Explicit**: Uses `DevToolsContext` to manage dependencies.
22+
23+
## Migration Guide
24+
25+
### 1. Replace Heavy Helpers
26+
Avoid `describeWithEnvironment` or `describeWithMockConnection`.
27+
28+
Instead, use standard `describe` and initialize environment hooks at the top-level `describe` block. **Crucial:** Without `setupRuntimeHooks`, tests creating SDK models will crash due to uninitialized experiments (e.g. `capture-node-creation-stacks`).
29+
30+
```ts
31+
import {setupLocaleHooks} from '../../testing/LocaleHelpers.js';
32+
import {setupSettingsHooks} from '../../testing/SettingsHelpers.js';
33+
import {setupRuntimeHooks} from '../../testing/RuntimeHelpers.js';
34+
import {TestUniverse} from '../../testing/TestUniverse.js';
35+
36+
describe('MyComponent', () => {
37+
setupLocaleHooks();
38+
setupSettingsHooks();
39+
setupRuntimeHooks();
40+
41+
let universe: TestUniverse;
42+
43+
beforeEach(() => {
44+
universe = new TestUniverse();
45+
});
46+
});
47+
```
48+
49+
### 2. Access Dependencies via Universe
50+
Instead of using `SDK.TargetManager.TargetManager.instance()`, use `universe.targetManager`. Use `universe.createTarget()` instead of the global `createTarget`.
51+
52+
```ts
53+
// OLD
54+
const target = createTarget();
55+
const targetManager = SDK.TargetManager.TargetManager.instance();
56+
57+
// NEW
58+
const target = universe.createTarget({url: urlString`http://example.com/`});
59+
const targetManager = universe.targetManager;
60+
```
61+
62+
#### Mocking CDP Traffic
63+
If the test used `describeWithMockConnection` and global `setMockConnectionResponseHandler` to stub CDP traffic, you can migrate this by passing a `MockCDPConnection` to `universe.createTarget()`. This allows stubbing out CDP traffic scoped to a specific target tree rather than globally.
64+
65+
```ts
66+
import {MockCDPConnection} from '../../testing/MockCDPConnection.js';
67+
68+
const cdpConnection = new MockCDPConnection([
69+
{
70+
method: 'Network.getResponseBody',
71+
response: () => ({body: 'mocked body', base64Encoded: false}),
72+
}
73+
]);
74+
75+
const target = universe.createTarget({connection: cdpConnection});
76+
```
77+
78+
> [!TIP]
79+
> **Legacy Target URLs**: `EnvironmentHelpers.createTarget()` defaults to `http://example.com/`. `TestUniverse.createTarget()` defaults to `about:blank`. If your test asserts against specific URLs, remember to pass the URL explicitly.
80+
81+
### 3. Dealing with Legacy Singletons & Helpers
82+
83+
For large integration tests, you may encounter code that strictly calls `SomeModule.instance()` or uses complex legacy helpers (like `createWorkspaceProject`).
84+
85+
**Do not use `setUpEnvironment()`** as it will create disconnected singletons. Instead, wire the singletons to your `TestUniverse` and stub the globals to bridge legacy helpers:
86+
87+
```ts
88+
beforeEach(async () => {
89+
universe = new TestUniverse();
90+
const {targetManager, workspace, settings} = universe;
91+
92+
// 1. Stub globals so legacy helpers use TestUniverse components
93+
sinon.stub(Workspace.Workspace.WorkspaceImpl, 'instance').returns(workspace);
94+
sinon.stub(SDK.TargetManager.TargetManager, 'instance').returns(targetManager);
95+
sinon.stub(Common.Settings.Settings, 'instance').returns(settings);
96+
97+
// 2. Initialize interdependent singletons in the correct order
98+
SDK.NetworkManager.MultitargetNetworkManager.instance({forceNew: true, targetManager});
99+
100+
// 3. Now safe to use legacy helpers that rely on the above instances
101+
await createWorkspaceProject(urlString`file:///path/to/overrides`, [...]);
102+
});
103+
```
104+
105+
## Pitfalls & Troubleshooting
106+
107+
### Strict Equality in Protocol Responses (`assert.deepEqual`)
108+
Protocol requests/responses dynamically generated by Chrome (like Network conditions) can vary slightly (e.g., adding `connectionType`, `urlPattern`).
109+
- **Problem**: `assert.deepEqual(rules, [{...}])` will flake if unrequested fields are present.
110+
- **Solution**: Use `sinon.spy()` for handlers and assert with `sinon.assert.calledOnceWithMatch`:
111+
112+
```ts
113+
const emulateSpy = sinon.spy();
114+
connection.setHandler('Network.emulateNetworkConditionsByRule', request => {
115+
emulateSpy(request);
116+
return {result: {ruleIds: []}};
117+
});
118+
119+
// Matches only the fields you care about, ignoring extra protocol fields
120+
sinon.assert.calledOnceWithMatch(emulateSpy, {
121+
offline: false,
122+
matchedNetworkConditions: [sinon.match({ downloadThroughput: 1000 })],
123+
});
124+
```
125+
126+
### DOM Globals (`ReferenceError: FileReader is not defined`)
127+
Foundation tests run in Node.js where `window`, `FileReader`, and certain DOM string encodings don't exist.
128+
- **Fix**: Use isomorphic equivalents (e.g. `btoa()`, `Uint8Array`).
129+
- **Fix**: Abstract the APIs that are different between Node.js and Browser via `front_end/core/platform/api/HostRuntime.ts`.
130+
131+
### Initialization Order Lockups
132+
If a test times out (5000ms exceeded), it is usually an unhandled promise caused by a missing singleton. Double-check the constructor of the failing manager to see which `instance()` it listens to, and ensure that dependent singleton was created *first*.
133+
134+
## BUILD.gn Changes
135+
136+
When a module and its tests are ready, update `BUILD.gn`:
137+
138+
1. Change `devtools_module` to `devtools_foundation_module` for both the module and its unittests.
139+
2. Ensure the tests are grouped under a `foundation_unittests` target in the parent `BUILD.gn`.
140+
141+
```gn
142+
# front_end/my_module/BUILD.gn
143+
144+
devtools_foundation_module("my_module") {
145+
sources = [ "MyModule.ts" ]
146+
deps = [ "../../core/common:bundle" ]
147+
}
148+
149+
devtools_foundation_module("unittests") {
150+
testonly = true
151+
sources = [ "MyModule.test.ts" ]
152+
deps = [
153+
":my_module",
154+
"../../testing",
155+
]
156+
}
157+
```
158+
159+
## Verification
160+
161+
Foundation tests must pass in both Node.js and Browser runtimes.
162+
163+
### Run in Node.js
164+
```bash
165+
npm test -- front_end/core/sdk/NetworkManager.test.ts --node-unit-tests
166+
```
167+
168+
### Run in Browser
169+
```bash
170+
npm test -- front_end/core/sdk/NetworkManager.test.ts
171+
```

0 commit comments

Comments
 (0)