chrome-devtools-frontend
Version:
Chrome DevTools UI
120 lines (91 loc) • 5.97 kB
Markdown
# Resource management in DevTools
This document outlines how DevTools keeps track of resources like scripts and
HTML files, and how they interact with other features such as the Debugger.
The source code lives in the bindings/, persistence/ and workspace/ directories.
## Core concepts and classes
* **Project:** Interface to a collection of resources. DevTools supports
different project **types**. For example “filesystem”, for resources
originating from the developers local machine, and “network”, for actual page
resources. The **Project** interface abstracts away rudimentary file
operations. Depending on the **type**, a **Project** may be able to create,
rename or delete resources, or change the contents.
* **Workspace**: A collection of all the **Projects** currently in use.
Implemented as a singleton in WorkspaceImpl.ts.
* **UISourceCode:** An actual resource identified by its URL. Scripts and
stylesheets are prominent examples, but DevTools also uses more esoteric
**ResourceTypes** such as XHR, WebSocket or EventSource.
## Project types
A short overview over the different Project types and what **kind of resources**
they contain.
* **Network:** All resources loaded from the network are stored in network
projects. Different targets and/or **Resource** **types** may use different
projects. E.g. Each target has their own project containing only JavaScript
source maps.
* **Filesystem:** Resources stored on the developers local machine.
* Snippets are managed with a single Project just for snippets.
* Each local directory mapped into DevTools with the “Workspaces” feature has
its own project.
* Each directory used for the “Overrides” feature has a corresponding project
to manage the local files.
* **Formatter:** A single project of this type manages the formatted version of
script resources. That is the “pretty-print” feature for minified JS files.
* **ContentScripts**: Scripts from extensions running in the context of the page
itself. One project per target. Source maps for content scripts are managed by
separate, per target, projects. The source map projects also have the
**ContentScripts** type.
* **Service:** One project of this type per target. It holds placeholder
UISourceCodes for source maps while they are loaded. Once a source map
finishes loading, the placeholder is removed from the **Service** project.
* **Debugger:** One project of this type per target. Debugger projects store
parsed JS scripts (see next section).
## The “Debugger” project type
When V8 parses scripts, it sends out a
[“Debugger.ScriptParsed”](https://chromedevtools.github.io/devtools-protocol/tot/Debugger/#event-scriptParsed)
event with some details, including a unique script ID and the URL of the script.
For each “Debugger.ScriptParsed” event, DevTools creates a **Script** object and
an associated **UISourceCode** in the “debugger” project. It is important to
note that the URL of this “debugger” UISourceCode contains both the script ID as
well as the script name (not URL!) to uniquely identify it. This is because:
_The relationship between network/filesystem UISourceCodes and **Script**
**objects**/debugger UISourceCodes is 1:n._
For example if the same script is included twice on a page with <script>
elements, it will result in a single UISourceCode in the **Network** project but
**two Script** **objects** and two UISourceCodes in the **Debugger** project.
Similarly, every invocation of a Snippet will result in a separate **Script**
object per invocation while the Snippet itself is stored in a **Filesystem**
project.
## Mappings and bindings
As can be seen above, UISourceCodes in different projects can potentially be
related to one another. A minified script resource in a **scripts Network project**
might have a pretty-printed version in the **Formatter project** while the
source map for the minified script is stored in the **source map Network project**.
Once the minified script is parsed/executed by V8, it also has a corresponding
**Script object** and a UISourceCode in the **Debugger project**.
This brings us to mappings and bindings. The terminology is roughly:
* _A **binding** ties different UISourceCodes together and determines which
UISourceCodes relate to one another._
* _A **mapping** translates source positions between bound UISourceCodes._
## Binding implementations
There are a couple of classes tasked with establishing bindings between
UISourceCodes:
* **DebuggerWorkspaceBinding:** Responsible for scripts and source maps.
It ties together network/filesystem UISourceCodes with **Script** objects and
the debugger USourceCodes. Script source maps are also partially implemented
by this class.
* **CSSWorkspaceBinding:** Responsible for CSS and CSS source maps. DevTools can
handle source mapped CSS when it was authored in SASS and this class is
responsible for binding the corresponding UISourceCodes.
* **PersistenceBinding/PersistenceImpl/Automapping**: Responsible for the
[“Workspaces”](https://developer.chrome.com/docs/devtools/workspaces/)
feature. When a developer adds a local directory to DevTools that corresponds
to the pages sources, these classes establish and manage the binding between
the corresponding **Filesystem** and **Network** resources.
* **NetworkPersistenceManager**: Responsible for the
[“Local Overrides”](https://developer.chrome.com/blog/new-in-devtools-65/#overrides)
feature. It connects the **Network** resources with the corresponding
overwritten version in a **Filesystem** project. This class also handles
network request interceptions and determines whether to serve the original or
the overwritten UISourceCode.
Please keep in mind that many of these classes have gathered additional
responsibilities over the years, so the concepts presented above might not
always cleanly apply or be apparent in code.