From 813d9049e134d08627f877798febf823e0c9b976 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Thu, 23 Jun 2022 10:43:34 -0700 Subject: [PATCH 01/13] Migrate modules and locations to null safety --- dwds/lib/src/debugging/location.dart | 47 ++++++++++++++++++---------- dwds/lib/src/debugging/modules.dart | 42 ++++++++++++++----------- dwds/test/debugger_test.dart | 1 + dwds/test/location_test.dart | 1 + 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/dwds/lib/src/debugging/location.dart b/dwds/lib/src/debugging/location.dart index 30419d815..b9aacf699 100644 --- a/dwds/lib/src/debugging/location.dart +++ b/dwds/lib/src/debugging/location.dart @@ -2,10 +2,9 @@ // 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. -// @dart = 2.9 - import 'package:async/async.dart'; import 'package:dwds/src/loaders/require.dart'; +import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; import 'package:source_maps/parser.dart'; import 'package:source_maps/source_maps.dart'; @@ -46,7 +45,7 @@ class Location { // https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k return Location._( JsLocation.fromZeroBased(module, jsLine, jsColumn), - DartLocation.fromZeroBased(dartUri, dartLine, dartColumn), + DartLocation.fromZeroBased(dartUri, dartLine ?? 0, dartColumn ?? 0), ); } @@ -118,6 +117,8 @@ class JsLocation { /// Contains meta data for known [Location]s. class Locations { + final _logger = Logger('Locations'); + /// [Location] data for Dart server path. final Map> _sourceToLocation = {}; final Map>> _locationMemoizer = {}; @@ -134,7 +135,7 @@ class Locations { final Modules _modules; final String _root; - String _entrypoint; + late String _entrypoint; Locations(this._assetReader, this._modules, this._root); @@ -151,7 +152,11 @@ class Locations { /// Returns all [Location] data for a provided Dart source. Future> locationsForDart(String serverPath) async { final module = await _modules.moduleForSource(serverPath); - await _locationsForModule(module); + if (module == null) { + _logger.warning('No module for server path $serverPath'); + } else { + await _locationsForModule(module); + } return _sourceToLocation[serverPath] ?? {}; } @@ -161,13 +166,18 @@ class Locations { _entrypoint, Uri.parse(url).path); final cache = _moduleToLocations[module]; if (cache != null) return cache; - return await _locationsForModule(module) ?? {}; + if (module == null) { + _logger.warning('No module for $url'); + } else { + await _locationsForModule(module); + } + return _moduleToLocations[module] ?? {}; } /// Find the [Location] for the given Dart source position. /// /// The [line] number is 1-based. - Future locationForDart(DartUri uri, int line, int column) async { + Future locationForDart(DartUri uri, int line, int column) async { final locations = await locationsForDart(uri.serverPath); return _bestDartLocation(locations, line, column); } @@ -175,7 +185,7 @@ class Locations { /// Find the [Location] for the given JS source position. /// /// The [line] number is 0-based. - Future locationForJs(String url, int line, int column) async { + Future locationForJs(String url, int line, int column) async { final locations = await locationsForUrl(url); return _bestJsLocation(locations, line, column); } @@ -185,9 +195,9 @@ class Locations { /// Dart columns for breakpoints are either exact or start at the /// beginning of the line - return the first existing location /// that comes after the given column. - Location _bestDartLocation( + Location? _bestDartLocation( Iterable locations, int line, int column) { - Location bestLocation; + Location? bestLocation; for (var location in locations) { if (location.dartLocation.line == line && location.dartLocation.column >= column) { @@ -209,8 +219,9 @@ class Locations { /// the closest location to the current one: /// /// https://github.com/microsoft/vscode-js-debug/blob/536f96bae61a3d87546b61bc7916097904c81429/src/common/sourceUtils.ts#L286 - Location _bestJsLocation(Iterable locations, int line, int column) { - Location bestLocation; + Location? _bestJsLocation( + Iterable locations, int line, int column) { + Location? bestLocation; for (var location in locations) { if (location.jsLocation.compareToLine(line, column) <= 0) { bestLocation ??= location; @@ -239,9 +250,10 @@ class Locations { .add(location); } for (var lineNumber in lineNumberToLocation.keys) { + final location = lineNumberToLocation[lineNumber]!; tokenPosTable.add([ lineNumber, - for (var location in lineNumberToLocation[lineNumber]) ...[ + for (var location in location) ...[ location.tokenPos, location.dartLocation.column ] @@ -259,11 +271,12 @@ class Locations { Future> _locationsForModule(String module) async { _locationMemoizer.putIfAbsent(module, () => AsyncMemoizer()); - return await _locationMemoizer[module].runOnce(() async { - if (module == null) return {}; - if (_moduleToLocations[module] != null) return _moduleToLocations[module]; + return await _locationMemoizer[module]!.runOnce(() async { + if (_moduleToLocations.containsKey(module)) { + return _moduleToLocations[module]!; + } final result = {}; - if (module?.isEmpty ?? true) return _moduleToLocations[module] = result; + if (module.isEmpty) return _moduleToLocations[module] = result; if (module.endsWith('dart_sdk') || module.endsWith('dart_library')) { return result; } diff --git a/dwds/lib/src/debugging/modules.dart b/dwds/lib/src/debugging/modules.dart index 4b41f10f9..5b3e994c1 100644 --- a/dwds/lib/src/debugging/modules.dart +++ b/dwds/lib/src/debugging/modules.dart @@ -2,15 +2,15 @@ // 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. -// @dart = 2.9 - import 'package:async/async.dart'; +import 'package:logging/logging.dart'; import '../loaders/strategy.dart'; import '../utilities/dart_uri.dart'; /// Tracks modules for the compiled application. class Modules { + final _logger = Logger('Modules'); final String _root; // The Dart server path to containing module. @@ -22,9 +22,9 @@ class Modules { final Map _libraryToModule = {}; - String _entrypoint; + late String _entrypoint; - Modules(String root) : _root = root == '' ? '/' : root; + Modules(this._root); /// Initializes the mapping from source to module. /// @@ -41,18 +41,18 @@ class Modules { } /// Returns the containing module for the provided Dart server path. - Future moduleForSource(String serverPath) async { + Future moduleForSource(String serverPath) async { await _moduleMemoizer.runOnce(_initializeMapping); return _sourceToModule[serverPath]; } /// Returns the containing library importUri for the provided Dart server path. - Future libraryForSource(String serverPath) async { + Future libraryForSource(String serverPath) async { await _moduleMemoizer.runOnce(_initializeMapping); return _sourceToLibrary[serverPath]; } - Future moduleForlibrary(String libraryUri) async { + Future moduleForlibrary(String libraryUri) async { await _moduleMemoizer.runOnce(_initializeMapping); return _libraryToModule[libraryUri]; } @@ -71,21 +71,27 @@ class Modules { final scriptToModule = await provider.scriptToModule; for (var library in libraryToScripts.keys) { + final scripts = libraryToScripts[library]!; final libraryServerPath = library.startsWith('dart:') ? library : DartUri(library, _root).serverPath; - _sourceToModule[libraryServerPath] = scriptToModule[library]; - _sourceToLibrary[libraryServerPath] = Uri.parse(library); - _libraryToModule[library] = scriptToModule[library]; - - for (var script in libraryToScripts[library]) { - final scriptServerPath = script.startsWith('dart:') - ? script - : DartUri(script, _root).serverPath; - - _sourceToModule[scriptServerPath] = scriptToModule[library]; - _sourceToLibrary[scriptServerPath] = Uri.parse(library); + if (scriptToModule.containsKey(library)) { + final module = scriptToModule[library]!; + _sourceToModule[libraryServerPath] = module; + _sourceToLibrary[libraryServerPath] = Uri.parse(library); + _libraryToModule[library] = module; + + for (var script in scripts) { + final scriptServerPath = script.startsWith('dart:') + ? script + : DartUri(script, _root).serverPath; + + _sourceToModule[scriptServerPath] = module; + _sourceToLibrary[scriptServerPath] = Uri.parse(library); + } + } else { + _logger.warning('No module found for library $library'); } } } diff --git a/dwds/test/debugger_test.dart b/dwds/test/debugger_test.dart index bf82829cf..5c3c49f0f 100644 --- a/dwds/test/debugger_test.dart +++ b/dwds/test/debugger_test.dart @@ -102,6 +102,7 @@ void main() async { globalLoadStrategy = TestStrategy(); final root = 'fakeRoot'; locations = Locations(FakeAssetReader(), FakeModules(), root); + locations.initialize('fake_entrypoint'); skipLists = SkipLists(); debugger = await Debugger.create( webkitDebugger, diff --git a/dwds/test/location_test.dart b/dwds/test/location_test.dart index 22d837f51..6390b6c8e 100644 --- a/dwds/test/location_test.dart +++ b/dwds/test/location_test.dart @@ -24,6 +24,7 @@ void main() { final assetReader = FakeAssetReader(); final modules = MockModules(); final locations = Locations(assetReader, modules, ''); + locations.initialize('fake_entrypoint'); group('JS locations |', () { group('location |', () { From 66c26e2022f9f42b5b038996b4a1990d39e035cf Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Fri, 24 Jun 2022 09:39:30 -0700 Subject: [PATCH 02/13] Remove circular dependencies --- dwds/lib/src/debugging/classes.dart | 20 +- dwds/lib/src/debugging/debugger.dart | 46 ++-- dwds/lib/src/debugging/inspector.dart | 203 +++++---------- dwds/lib/src/debugging/instance.dart | 11 +- dwds/lib/src/debugging/libraries.dart | 5 +- dwds/lib/src/debugging/metadata/class.dart | 17 +- .../src/services/chrome_proxy_service.dart | 231 +++++++++++------- .../src/services/expression_evaluator.dart | 12 +- dwds/lib/src/utilities/domain.dart | 114 +++++++-- dwds/test/chrome_proxy_service_test.dart | 4 +- dwds/test/debugger_test.dart | 2 +- dwds/test/evaluate_common.dart | 2 +- dwds/test/fixtures/fakes.dart | 19 +- dwds/test/inspector_test.dart | 35 ++- dwds/test/instance_test.dart | 35 ++- dwds/test/variable_scope_test.dart | 3 +- 16 files changed, 396 insertions(+), 363 deletions(-) diff --git a/dwds/lib/src/debugging/classes.dart b/dwds/lib/src/debugging/classes.dart index 112ad8994..71944df74 100644 --- a/dwds/lib/src/debugging/classes.dart +++ b/dwds/lib/src/debugging/classes.dart @@ -11,30 +11,16 @@ import '../../src/services/chrome_debug_exception.dart'; import '../loaders/strategy.dart'; import '../utilities/domain.dart'; import '../utilities/shared.dart'; -import 'inspector.dart'; import 'metadata/class.dart'; -/// A hard-coded ClassRef for the Closure class. -final classRefForClosure = classRefFor('dart:core', 'Closure'); - -/// A hard-coded ClassRef for the String class. -final classRefForString = classRefFor('dart:core', InstanceKind.kString); - -/// A hard-coded ClassRef for a (non-existent) class called Unknown. -final classRefForUnknown = classRefFor('dart:core', 'Unknown'); - -/// Returns a [ClassRef] for the provided library ID and class name. -ClassRef classRefFor(String libraryId, String name) => ClassRef( - id: 'classes|$libraryId|$name', - name: name, - library: LibraryRef(id: libraryId, name: libraryId, uri: libraryId)); /// Keeps track of Dart classes available in the running application. class ClassHelper extends Domain { /// Map of class ID to [Class]. final _classes = {}; - ClassHelper(AppInspector Function() provider) : super(provider) { + ClassHelper(AppInspectorInterface appInspector) { + inspector = appInspector; final staticClasses = [ classRefForClosure, classRefForString, @@ -67,7 +53,7 @@ class ClassHelper extends Domain { if (libraryId == 'null') { throw UnsupportedError('unknown library: $libraryId'); } - final libraryRef = await inspector.libraryHelper.libraryRefFor(libraryId); + final libraryRef = await inspector.libraryRefFor(libraryId); if (libraryRef == null) { throw Exception('Could not find library: $libraryId'); } diff --git a/dwds/lib/src/debugging/debugger.dart b/dwds/lib/src/debugging/debugger.dart index 85bb1eb14..ed1d94ad8 100644 --- a/dwds/lib/src/debugging/debugger.dart +++ b/dwds/lib/src/debugging/debugger.dart @@ -15,7 +15,6 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart' hide StackTrace; import '../loaders/strategy.dart'; -import '../services/chrome_proxy_service.dart'; import '../services/chrome_debug_exception.dart'; import '../utilities/conversions.dart'; import '../utilities/dart_uri.dart'; @@ -28,6 +27,10 @@ import 'location.dart'; import 'remote_debugger.dart'; import 'skip_list.dart'; +/// Adds [event] to the stream with [streamId] if there is anybody listening +/// on that stream. +typedef StreamNotify = void Function(String streamId, Event event); + /// Converts from ExceptionPauseMode strings to [PauseState] enums. /// /// Values defined in: @@ -51,16 +54,13 @@ class Debugger extends Domain { Debugger._( this._remoteDebugger, this._streamNotify, - AppInspectorProvider provider, this._locations, this._skipLists, this._root, - ) : _breakpoints = _Breakpoints( + ) : _breakpoints = _Breakpoints( locations: _locations, - provider: provider, remoteDebugger: _remoteDebugger, - root: _root), - super(provider); + root: _root); /// The breakpoints we have set so far, indexable by either /// Dart or JS ID. @@ -86,6 +86,11 @@ class Debugger extends Domain { bool _isStepping = false; + void updateInspector(AppInspectorInterface appInspector) { + inspector = appInspector; + _breakpoints.inspector = appInspector; + } + Future pause() async { _isStepping = false; final result = await _remoteDebugger.pause(); @@ -93,8 +98,7 @@ class Debugger extends Domain { return Success(); } - Future setExceptionPauseMode(String isolateId, String mode) async { - checkIsolate('setExceptionPauseMode', isolateId); + Future setExceptionPauseMode(String mode) async { mode = mode?.toLowerCase(); if (!_pauseModePauseStates.containsKey(mode)) { throwInvalidParam('setExceptionPauseMode', 'Unsupported mode: $mode'); @@ -117,9 +121,7 @@ class Debugger extends Domain { /// /// Note that stepping will automatically continue until Chrome is paused at /// a location for which we have source information. - Future resume(String isolateId, - {String step, int frameIndex}) async { - checkIsolate('resume', isolateId); + Future resume({String step, int frameIndex}) async { if (frameIndex != null) { throw ArgumentError('FrameIndex is currently unsupported.'); } @@ -152,9 +154,7 @@ class Debugger extends Domain { /// Returns null if the debugger is not paused. /// /// The returned stack will contain up to [limit] frames if provided. - Future getStack(String isolateId, {int limit}) async { - checkIsolate('getStack', isolateId); - + Future getStack({int limit}) async { if (stackComputer == null) { throw RPCError('getStack', RPCError.kInternalError, 'Cannot compute stack when application is not paused'); @@ -170,7 +170,6 @@ class Debugger extends Domain { static Future create( RemoteDebugger remoteDebugger, StreamNotify streamNotify, - AppInspectorProvider appInspectorProvider, Locations locations, SkipLists skipLists, String root, @@ -178,7 +177,6 @@ class Debugger extends Domain { final debugger = Debugger._( remoteDebugger, streamNotify, - appInspectorProvider, locations, skipLists, root, @@ -224,13 +222,11 @@ class Debugger extends Domain { /// /// Note that line and column are Dart source locations and are one-based. Future addBreakpoint( - String isolateId, String scriptId, int line, { int column, }) async { column ??= 0; - checkIsolate('addBreakpoint', isolateId); final breakpoint = await _breakpoints.add(scriptId, line, column); _notifyBreakpoint(breakpoint); return breakpoint; @@ -265,7 +261,6 @@ class Debugger extends Domain { // them back. for (var breakpoint in disabledBreakpoints) { await addBreakpoint( - inspector.isolate.id, (await _updatedScriptRefFor(breakpoint)).id, _lineNumberFor(breakpoint), column: _columnNumberFor(breakpoint)); @@ -283,9 +278,7 @@ class Debugger extends Domain { } /// Remove a Dart breakpoint. - Future removeBreakpoint( - String isolateId, String breakpointId) async { - checkIsolate('removeBreakpoint', isolateId); + Future removeBreakpoint(String breakpointId) async { if (!_breakpoints._bpByDartId.containsKey(breakpointId)) { throwInvalidParam( 'removeBreakpoint', 'invalid breakpoint id $breakpointId'); @@ -362,7 +355,7 @@ class Debugger extends Domain { // We return one level of properties from this object. Sub-properties are // another round trip. final instanceRef = - await inspector.instanceHelper.instanceRefFor(property.value); + await inspector.instanceRefFor(property.value); // Skip null instance refs, which we get for weird objects, e.g. // properties that are getter/setter pairs. // TODO(alanknight): Handle these properly. @@ -552,7 +545,7 @@ class Debugger extends Domain { if (map['type'] == 'object') { // The className here is generally 'DartError'. final obj = RemoteObject(map); - exception = await inspector.instanceHelper.instanceRefFor(obj); + exception = await inspector.instanceRefFor(obj); // TODO: The exception object generally doesn't get converted to a // Dart object (and instead has a classRef name of 'NativeJavaScriptObject'). @@ -562,7 +555,7 @@ class Debugger extends Domain { final description = await inspector.mapExceptionStackTrace(obj.description); exception = - await inspector.instanceHelper.instanceRefFor(description); + await inspector.instanceRefFor(description); } else { exception = null; } @@ -766,10 +759,9 @@ class _Breakpoints extends Domain { _Breakpoints({ @required this.locations, - @required AppInspectorProvider provider, @required this.remoteDebugger, @required this.root, - }) : super(provider); + }); Future _createBreakpoint( String id, String scriptId, int line, int column) async { diff --git a/dwds/lib/src/debugging/inspector.dart b/dwds/lib/src/debugging/inspector.dart index bc76be14c..7028766b4 100644 --- a/dwds/lib/src/debugging/inspector.dart +++ b/dwds/lib/src/debugging/inspector.dart @@ -20,7 +20,6 @@ import '../utilities/domain.dart'; import '../utilities/sdk_configuration.dart'; import '../utilities/shared.dart'; import 'classes.dart'; -import 'debugger.dart'; import 'execution_context.dart'; import 'instance.dart'; import 'libraries.dart'; @@ -30,7 +29,7 @@ import 'libraries.dart'; /// /// Provides information about currently loaded scripts and objects and support /// for eval. -class AppInspector extends Domain { +class AppInspector implements AppInspectorInterface { final _scriptCacheMemoizer = AsyncMemoizer>(); Future> get scriptRefs => _populateScriptCaches(); @@ -49,16 +48,23 @@ class AppInspector extends Domain { /// Map of [Library] id to included [ScriptRef]s. final _libraryIdToScriptRefs = >{}; - final RemoteDebugger remoteDebugger; - final Debugger debugger; - final Isolate isolate; - final IsolateRef isolateRef; - final AppConnection appConnection; + final RemoteDebugger _remoteDebugger; + RemoteDebugger get remoteDebugger => _remoteDebugger; + + final Isolate _isolate; + Isolate get isolate => _isolate; + + final IsolateRef _isolateRef; + IsolateRef get isolateRef => _isolateRef; + + final AppConnection _appConnection; + AppConnection get appConnection => _appConnection; + final ExecutionContext _executionContext; - final LibraryHelper libraryHelper; - final ClassHelper classHelper; - final InstanceHelper instanceHelper; + LibraryHelper _libraryHelper; + ClassHelper _classHelper; + InstanceHelper _instanceHelper; final AssetReader _assetReader; final Locations _locations; @@ -74,28 +80,27 @@ class AppInspector extends Domain { static final exceptionMessageRegex = RegExp(r'^.*$', multiLine: true); AppInspector._( - this.appConnection, - this.isolate, - this.remoteDebugger, - this.debugger, - this.libraryHelper, - this.classHelper, - this.instanceHelper, + this._appConnection, + this._isolate, + this._remoteDebugger, this._assetReader, this._locations, this._root, this._executionContext, this._sdkConfiguration, - ) : isolateRef = _toIsolateRef(isolate), - super.forInspector(); + ) : _isolateRef = _toIsolateRef(_isolate); - /// We are the inspector, so this getter is trivial. - @override - AppInspector get inspector => this; + Future initialize( + LibraryHelper libraryHelper, + ClassHelper classHelper, + InstanceHelper instanceHelper, + ) async { + _libraryHelper = libraryHelper; + _classHelper = classHelper; + _instanceHelper = instanceHelper; - Future _initialize() async { - final libraries = await libraryHelper.libraryRefs; - isolate.rootLib = await libraryHelper.rootLib; + final libraries = await _libraryHelper.libraryRefs; + isolate.rootLib = await _libraryHelper.rootLib; isolate.libraries.addAll(libraries); final scripts = await scriptRefs; @@ -114,62 +119,26 @@ class AppInspector extends Domain { isSystemIsolate: isolate.isSystemIsolate, ); - static Future initialize( + static AppInspector create( AppConnection appConnection, + Isolate isolate, RemoteDebugger remoteDebugger, AssetReader assetReader, Locations locations, String root, - Debugger debugger, ExecutionContext executionContext, SdkConfiguration sdkConfiguration, - ) async { - final id = createId(); - final time = DateTime.now().millisecondsSinceEpoch; - final name = 'main()'; - final isolate = Isolate( - id: id, - number: id, - name: name, - startTime: time, - runnable: true, - pauseOnExit: false, - pauseEvent: Event( - kind: EventKind.kPauseStart, - timestamp: time, - isolate: IsolateRef( - id: id, - name: name, - number: id, - isSystemIsolate: false, - )), - livePorts: 0, - libraries: [], - breakpoints: [], - exceptionPauseMode: debugger.pauseState, - isSystemIsolate: false, - isolateFlags: []) - ..extensionRPCs = []; - AppInspector appInspector; - AppInspector provider() => appInspector; - final libraryHelper = LibraryHelper(provider); - final classHelper = ClassHelper(provider); - final instanceHelper = InstanceHelper(provider); - appInspector = AppInspector._( + ) { + final appInspector = AppInspector._( appConnection, isolate, remoteDebugger, - debugger, - libraryHelper, - classHelper, - instanceHelper, assetReader, locations, root, executionContext, sdkConfiguration, ); - await appInspector._initialize(); return appInspector; } @@ -195,7 +164,7 @@ class AppInspector extends Domain { /// Call a method by name on [receiver], with arguments [positionalArgs] and /// [namedArgs]. - Future invokeMethod(RemoteObject receiver, String methodName, + Future _invokeMethod(RemoteObject receiver, String methodName, [List positionalArgs = const [], Map namedArgs = const {}]) async { // TODO(alanknight): Support named arguments. @@ -251,22 +220,6 @@ class AppInspector extends Domain { return RemoteObject(result.result['result'] as Map); } - Future evaluate( - String isolateId, String targetId, String expression, - {Map scope}) async { - scope ??= {}; - final library = await getLibrary(isolateId, targetId); - if (library == null) { - throw UnsupportedError( - 'Evaluate is only supported when `targetId` is a library.'); - } - if (scope.isNotEmpty) { - return evaluateInLibrary(library, scope, expression); - } else { - return evaluateJsExpressionOnLibrary(expression, library.uri); - } - } - /// Invoke the function named [selector] on the object identified by /// [targetId]. /// @@ -274,18 +227,17 @@ class AppInspector extends Domain { /// invoking a top-level function. The [arguments] are always strings that are /// Dart object Ids (which can also be Chrome RemoteObject objectIds that are /// for non-Dart JS objects.) - Future invoke(String isolateId, String targetId, + Future invoke(String targetId, String selector, List arguments) async { - checkIsolate('invoke', isolateId); final remoteArguments = arguments.cast().map(remoteObjectFor).toList(); // We special case the Dart library, where invokeMethod won't work because // it's not really a Dart object. if (isLibraryId(targetId)) { - final library = await getObject(isolateId, targetId) as Library; + final library = await getObject(targetId) as Library; return await _invokeLibraryFunction(library, selector, remoteArguments); } else { - return invokeMethod(remoteObjectFor(targetId), selector, remoteArguments); + return _invokeMethod(remoteObjectFor(targetId), selector, remoteArguments); } } @@ -298,21 +250,6 @@ class AppInspector extends Domain { arguments); } - /// Evaluate [expression] as a member/message of the library identified by - /// [libraryUri]. - /// - /// That is, we will just do 'library.$expression' - Future evaluateJsExpressionOnLibrary( - String expression, String libraryUri) { - final evalExpression = ''' -(function() { - ${globalLoadStrategy.loadLibrarySnippet(libraryUri)}; - return library.$expression; -})(); -'''; - return jsEvaluate(evalExpression); - } - /// Evaluate [expression] by calling Chrome's Runtime.evaluate. Future jsEvaluate(String expression) async { // TODO(alanknight): Support a version with arguments if needed. @@ -341,21 +278,6 @@ class AppInspector extends Domain { return jsCallFunctionOn(remoteLibrary, jsFunction, arguments); } - /// Evaluate [expression] from [library] with [scope] as - /// arguments. - Future evaluateInLibrary( - Library library, Map scope, String expression) async { - final argsString = scope.keys.join(', '); - final arguments = scope.values.map(remoteObjectFor).toList(); - final evalExpression = ''' -function($argsString) { - ${globalLoadStrategy.loadLibrarySnippet(library.uri)}; - return library.$expression; -} - '''; - return _evaluateInLibrary(library, evalExpression, arguments); - } - /// Call [function] with objects referred by [argumentIds] as arguments. Future callFunction( String function, Iterable argumentIds) async { @@ -363,29 +285,34 @@ function($argsString) { return _jsCallFunction(function, arguments); } - Future getLibrary(String isolateId, String objectId) async { - if (isolateId != isolate.id) return null; - final libraryRef = await libraryHelper.libraryRefFor(objectId); + Future instanceRefFor(Object value) => _instanceHelper.instanceRefFor(value); + + Future instanceFor(Object value) => _instanceHelper.instanceFor(value); + + Future libraryRefFor(String objectId) => _libraryHelper.libraryRefFor(objectId); + + Future getLibrary(String objectId) async { + final libraryRef = await libraryRefFor(objectId); if (libraryRef == null) return null; - return libraryHelper.libraryFor(libraryRef); + return _libraryHelper.libraryFor(libraryRef); } - Future getObject(String isolateId, String objectId, + Future getObject(String objectId, {int offset, int count}) async { try { - final library = await getLibrary(isolateId, objectId); + final library = await getLibrary(objectId); if (library != null) { return library; } - final clazz = await classHelper.forObjectId(objectId); + final clazz = await _classHelper.forObjectId(objectId); if (clazz != null) { return clazz; } final scriptRef = _scriptRefsById[objectId]; if (scriptRef != null) { - return await _getScript(isolateId, scriptRef); + return await _getScript(scriptRef); } - final instance = await instanceHelper + final instance = await _instanceHelper .instanceFor(remoteObjectFor(objectId), offset: offset, count: count); if (instance != null) { return instance; @@ -398,7 +325,7 @@ function($argsString) { 'are supported for getObject'); } - Future