| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import '../debugging/execution_context.dart'; |
| import '../loaders/strategy.dart'; |
| import '../utilities/dart_uri.dart'; |
| import '../utilities/shared.dart'; |
| import 'remote_debugger.dart'; |
| |
| /// Contains meta data and helpful methods for DDC modules. |
| class Modules { |
| final String _root; |
| final RemoteDebugger _remoteDebugger; |
| final ExecutionContext _executionContext; |
| // The Dart server path to containing module. |
| final _sourceToModule = <String, String>{}; |
| // The Dart server path to library import uri |
| final _sourceToLibrary = <String, Uri>{}; |
| Completer<bool> _moduleCompleter = Completer<bool>(); |
| |
| // The Chrome script ID to corresponding module. |
| final _scriptIdToModule = <String, String>{}; |
| |
| // The module to corresponding Chrome script ID. |
| final _moduleToScriptId = <String, String>{}; |
| |
| Modules( |
| this._remoteDebugger, |
| String root, |
| this._executionContext, |
| ) : _root = root == '' ? '/' : root; |
| |
| /// Initializes the mapping from source to module. |
| /// |
| /// Intended to be called multiple times throughout the development workflow, |
| /// e.g. after a hot-reload. |
| void initialize() { |
| // We only clear the source to module mapping as script IDs may persist |
| // across hot reloads. |
| _sourceToModule.clear(); |
| _sourceToLibrary.clear(); |
| _moduleCompleter = Completer<bool>(); |
| } |
| |
| /// Returns the module for the Chrome script ID. |
| Future<String> moduleForScriptId(String scriptId) async => |
| _scriptIdToModule[scriptId]; |
| |
| /// Returns the Chrome script ID for the provided module. |
| Future<String> scriptIdForModule(String module) async => |
| _moduleToScriptId[module]; |
| |
| /// Returns the containing module for the provided Dart server path. |
| Future<String> moduleForSource(String serverPath) async { |
| await _initializeMapping(); |
| return _sourceToModule[serverPath]; |
| } |
| |
| /// Returns the containing library importUri for the provided Dart server path. |
| Future<Uri> libraryForSource(String serverPath) async { |
| await _initializeMapping(); |
| return _sourceToLibrary[serverPath]; |
| } |
| |
| // Returns mapping from server paths to library paths |
| Future<Map<String, String>> modules() async { |
| await _initializeMapping(); |
| return _sourceToModule; |
| } |
| |
| /// Checks if the [url] correspond to a module and stores meta data. |
| Future<Null> noteModule(String url, String scriptId) async { |
| var path = Uri.parse(url).path; |
| if (path == null) return; |
| var module = globalLoadStrategy.moduleForServerPath(path); |
| if (module == null) return; |
| _scriptIdToModule[scriptId] = module; |
| _moduleToScriptId[module] = scriptId; |
| } |
| |
| /// Initializes [_sourceToModule]. |
| Future<void> _initializeMapping() async { |
| if (_moduleCompleter.isCompleted) return; |
| // TODO(grouma) - We should talk to the compiler directly to greatly |
| // improve the performance here. |
| var expression = ''' |
| (function() { |
| var dart = ${globalLoadStrategy.loadModuleSnippet}('dart_sdk').dart; |
| var result = {}; |
| dart.getModuleNames().forEach(function(module){ |
| Object.keys(dart.getModuleLibraries(module)).forEach( |
| function(script){ |
| result[script] = module; |
| }); |
| }); |
| return result; |
| })(); |
| '''; |
| var response = |
| await _remoteDebugger.sendCommand('Runtime.evaluate', params: { |
| 'expression': expression, |
| 'returnByValue': true, |
| 'contextId': await _executionContext.id, |
| }); |
| handleErrorIfPresent(response); |
| var value = response.result['result']['value'] as Map<String, dynamic>; |
| for (var dartScript in value.keys) { |
| if (!dartScript.endsWith('.dart')) continue; |
| var serverPath = DartUri(dartScript, _root).serverPath; |
| _sourceToModule[serverPath] = value[dartScript] as String; |
| _sourceToLibrary[serverPath] = Uri.parse(dartScript); |
| } |
| _moduleCompleter.complete(); |
| } |
| } |