DevTools foundation is the core business logic of DevTools: mainly core/ and models/. The difference between “foundation” and the rest of DevTools is that the code is targeted not just for the browser, but also the Node.js runtime. As such, allowed use of APIs is restricted to what is available in both runtimes.
A DevToolsUniverse is a concrete, encapsulated instance of “foundation” scoped to a single root CDP target. It is valid to create multiple DevToolsUniverse instances simultaneously.
The following is a prioritized list of architectural shortcomings and refactoring projects aimed at reducing coupling, eliminating global state, and improving the modularity of the DevTools foundation.
models/text_utils to core/text_utils [DONE]front_end/core/sdk depend directly on front_end/models/text_utils for basic text structures (layering violation).text_utils contains fundamental, non-business-logic utilities (TextRange, TextCursor, ContentData, ContentProvider) that represent the base data structures of the editor, debugger, and network panels. It only depends on core/common and core/platform. Moving it to core is a natural fit and resolves the majority of core -> models layering violations.front_end/models/text_utils to front_end/core/text_utils.ResourceMapping <-> Bindings)ResourceMapping and DebuggerWorkspaceBinding/CSSWorkspaceBinding prevent isolated testing.ResourceMapping from concrete bindings allows better testing and modularity.ResourceMapping (Dependency Inversion). DebuggerWorkspaceBinding and CSSWorkspaceBinding should implement these interfaces and register themselves, allowing ResourceMapping to invoke them without depending on concrete classes.IgnoreListManager from workspace to bindingsmodels/workspace depends on core/sdk via IgnoreListManager.ts.UISourceCode.isIgnoreListed() (and related methods in UILocation) from models/workspace.IgnoreListManager directly.IgnoreListManager.ts to models/bindings.workspace on sdk.Workspace.Project from SDK.TargetWorkspace.Project exposes target(), coupling the VFS to runtime targets.target() from the Project interface and ProjectStore in front_end/models/workspace/WorkspaceImpl.ts.bindings module, maintain a private WeakMap<Workspace.Project, SDK.Target.Target> to associate projects with targets.NetworkProject.targetForUISourceCode(uiSourceCode) to look up the target from this WeakMap.core/sdk from models/formatter (AST Scope Fallback)SDK/SourceMap.ts depends on models/formatter for fallback scope calculation.SDK should not depend on high-level formatting/parsing worker pools.SourceMap.ts and expose a clean API (e.g., setScopesInfo(...)).front_end/models/bindings (e.g., in DebuggerWorkspaceBinding), which coordinates script and source map loading.SourceMap object.DebuggerWorkspaceBinding.instance() directly.InspectorFrontendHostInstance and Root.Runtime.hostConfig are treated as global mutable singletons. Core classes (Connections, IsolatedFileSystemManager, FileManager) and UI components access them directly, leading to global state pollution and state leaks in tests.DevToolsUniverse instances, both the host interface and host configuration must be scoped to the universe context.InspectorFrontendHostAPI (wrapped in ScopedInspectorFrontendHost) in the DevToolsUniverse context.Connections, IsolatedFileSystemManager, FileManager, UserMetrics) to receive the scoped host via constructor injection.HostConfigProvider service in the Universe context to manage HostConfig fetching and caching.HostConfigTracker in AidaClient.ts to HostConfigProvider.Root.Runtime.hostConfig to allow gradual migration of the 200+ call sites.InspectorFrontendHost.ts..instance() for bindings, causing state leaks in tests.Universe and inject them via the view loading pipeline.-meta.ts files) to pass these bindings to panel constructors upon initialization, avoiding global calls in UI panels.persistence from bindingsmodels/persistence depends on models/bindings to check if a target is Node.js.persistence (which maps network files to local files) should ideally only depend on workspace and not on the complex debugger/bindings layer.Workspace.Project (e.g., isNodeProject) to avoid direct target queries.SourceFrameIssuesManager to bindingsmodels/issues_manager depends on workspace and bindings only for placing issue badges.issues_manager itself should be a clean, independent leaf module.SourceFrameIssuesManager.ts to models/bindings/ and remove workspace and bindings dependencies from issues_manager/BUILD.gn.Linkifier) depend on heavy concrete bindings.Common.Revealer.i18n (UI Localization)i18n for localized strings.