From c29e5f84b7ac1a372406b8cc9e5329273ffb9184 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:29:24 -0800 Subject: [PATCH] Do not persist breakpoints across hot restarts or page refreshes (#2371) --- dwds/CHANGELOG.md | 1 + dwds/lib/src/debugging/debugger.dart | 142 +++++++----------- dwds/lib/src/debugging/location.dart | 24 ++- dwds/lib/src/debugging/modules.dart | 10 ++ .../src/services/chrome_proxy_service.dart | 15 -- dwds/test/fixtures/fakes.dart | 7 + dwds/test/location_test.dart | 21 ++- dwds/test/reload_test.dart | 58 +------ dwds/test/restore_breakpoints_test.dart | 124 --------------- dwds/test/skip_list_test.dart | 17 ++- 10 files changed, 128 insertions(+), 291 deletions(-) delete mode 100644 dwds/test/restore_breakpoints_test.dart diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 596a25b57..80ab4e428 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -2,6 +2,7 @@ - Rename `dart_library.js` to `ddc_module_loader.js` to match SDK naming changes. - [#2360](https://github.com/dart-lang/webdev/pull/2360) - Implement `setFlag` when it is called with `pause_isolates_on_start`. - [#2373](https://github.com/dart-lang/webdev/pull/2373) +- Do not persist breakpoints across hot restarts or page reloads. - [#2371](https://github.com/dart-lang/webdev/pull/2371) ## 23.3.0 diff --git a/dwds/lib/src/debugging/debugger.dart b/dwds/lib/src/debugging/debugger.dart index b5af29092..c2e934605 100644 --- a/dwds/lib/src/debugging/debugger.dart +++ b/dwds/lib/src/debugging/debugger.dart @@ -18,6 +18,7 @@ import 'package:dwds/src/utilities/server.dart'; import 'package:dwds/src/utilities/shared.dart'; import 'package:dwds/src/utilities/synchronized.dart'; import 'package:logging/logging.dart'; +import 'package:path/path.dart' as p; import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart' hide StackTrace; @@ -36,6 +37,14 @@ const _pauseModePauseStates = { 'unhandled': PauseState.uncaught, }; +/// Mapping from the path of a script in Chrome to the Runtime.ScriptId Chrome +/// uses to reference it. +/// +/// See https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-ScriptId +/// +/// e.g. 'packages/myapp/main.dart.lib.js' -> '12' +final chromePathToRuntimeScriptId = {}; + class Debugger extends Domain { static final logger = Logger('Debugger'); @@ -44,18 +53,17 @@ class Debugger extends Domain { final StreamNotify _streamNotify; final Locations _locations; final SkipLists _skipLists; - final String _root; Debugger._( this._remoteDebugger, this._streamNotify, this._locations, this._skipLists, - this._root, + root, ) : _breakpoints = _Breakpoints( locations: _locations, remoteDebugger: _remoteDebugger, - root: _root, + root: root, ); /// The breakpoints we have set so far, indexable by either @@ -207,6 +215,7 @@ class Debugger extends Domain { // miss events. // Allow a null debugger/connection for unit tests. runZonedGuarded(() { + _remoteDebugger.onScriptParsed.listen(_scriptParsedHandler); _remoteDebugger.onPaused.listen(_pauseHandler); _remoteDebugger.onResumed.listen(_resumeHandler); _remoteDebugger.onTargetCrashed.listen(_crashHandler); @@ -253,67 +262,6 @@ class Debugger extends Domain { return breakpoint; } - Future _updatedScriptRefFor(Breakpoint breakpoint) async { - final oldRef = (breakpoint.location as SourceLocation).script; - final uri = oldRef?.uri; - if (uri == null) return null; - final dartUri = DartUri(uri, _root); - return await inspector.scriptRefFor(dartUri.serverPath); - } - - Future reestablishBreakpoints( - Set previousBreakpoints, - Set disabledBreakpoints, - ) async { - // Previous breakpoints were never removed from Chrome since we use - // `setBreakpointByUrl`. We simply need to update the references. - for (var breakpoint in previousBreakpoints) { - final dartBpId = breakpoint.id!; - final scriptRef = await _updatedScriptRefFor(breakpoint); - final scriptUri = scriptRef?.uri; - if (scriptRef != null && scriptUri != null) { - final jsBpId = _breakpoints.jsIdFor(dartBpId)!; - final updatedLocation = await _locations.locationForDart( - DartUri(scriptUri, _root), - _lineNumberFor(breakpoint), - _columnNumberFor(breakpoint), - ); - if (updatedLocation != null) { - final updatedBreakpoint = _breakpoints._dartBreakpoint( - scriptRef, - updatedLocation, - dartBpId, - ); - _breakpoints._note(bp: updatedBreakpoint, jsId: jsBpId); - _notifyBreakpoint(updatedBreakpoint); - } else { - logger.warning('Cannot update breakpoint $dartBpId:' - ' cannot update location.'); - } - } else { - logger.warning('Cannot update breakpoint $dartBpId:' - ' cannot find script ref.'); - } - } - - // Disabled breakpoints were actually removed from Chrome so simply add - // them back. - for (var breakpoint in disabledBreakpoints) { - final scriptRef = await _updatedScriptRefFor(breakpoint); - final scriptId = scriptRef?.id; - if (scriptId != null) { - await addBreakpoint( - scriptId, - _lineNumberFor(breakpoint), - column: _columnNumberFor(breakpoint), - ); - } else { - logger.warning('Cannot update disabled breakpoint ${breakpoint.id}:' - ' cannot find script ref.'); - } - } - } - void _notifyBreakpoint(Breakpoint breakpoint) { final event = Event( kind: EventKind.kBreakpointAdded, @@ -520,6 +468,31 @@ class Debugger extends Domain { return dartFrame; } + void _scriptParsedHandler(ScriptParsedEvent e) { + final scriptPath = _pathForChromeScript(e.script.url); + if (scriptPath != null) { + chromePathToRuntimeScriptId[scriptPath] = e.script.scriptId; + } + } + + String? _pathForChromeScript(String scriptUrl) { + final scriptPathSegments = Uri.parse(scriptUrl).pathSegments; + if (scriptPathSegments.isEmpty) { + return null; + } + + final isInternal = globalToolConfiguration.appMetadata.isInternalBuild; + const packagesDir = 'packages'; + if (isInternal && scriptUrl.contains(packagesDir)) { + final packagesIdx = scriptPathSegments.indexOf(packagesDir); + return p.joinAll(scriptPathSegments.sublist(packagesIdx)); + } + + // Note: Replacing "\" with "/" is necessary because `joinAll` uses "\" if + // the platform is Windows. However, only "/" is expected by the browser. + return p.joinAll(scriptPathSegments).replaceAll('\\', '/'); + } + /// Handles pause events coming from the Chrome connection. Future _pauseHandler(DebuggerPausedEvent e) async { final isolate = inspector.isolate; @@ -738,14 +711,6 @@ Future sendCommandAndValidateResult( return result; } -/// Returns the Dart line number for the provided breakpoint. -int _lineNumberFor(Breakpoint breakpoint) => - int.parse(breakpoint.id!.split('#').last.split(':').first); - -/// Returns the Dart column number for the provided breakpoint. -int _columnNumberFor(Breakpoint breakpoint) => - int.parse(breakpoint.id!.split('#').last.split(':').last); - /// Returns the breakpoint ID for the provided Dart script ID and Dart line /// number. String breakpointIdFor(String scriptId, int line, int column) => @@ -779,8 +744,10 @@ class _Breakpoints extends Domain { int line, int column, ) async { + print('creating breakpoint at $scriptId:$line:$column)'); final dartScript = inspector.scriptWithId(scriptId); final dartScriptUri = dartScript?.uri; + print('dart script uri is $dartScriptUri'); Location? location; if (dartScriptUri != null) { final dartUri = DartUri(dartScriptUri, root); @@ -853,22 +820,27 @@ class _Breakpoints extends Domain { /// Calls the Chrome protocol setBreakpoint and returns the remote ID. Future _setJsBreakpoint(Location location) { - // The module can be loaded from a nested path and contain an ETAG suffix. - final urlRegex = '.*${location.jsLocation.module}.*'; // Prevent `Aww, snap!` errors when setting multiple breakpoints // simultaneously by serializing the requests. return _queue.run(() async { - final breakPointId = await sendCommandAndValidateResult( - remoteDebugger, - method: 'Debugger.setBreakpointByUrl', - resultField: 'breakpointId', - params: { - 'urlRegex': urlRegex, - 'lineNumber': location.jsLocation.line, - 'columnNumber': location.jsLocation.column, - }, - ); - return breakPointId; + final scriptId = location.jsLocation.runtimeScriptId; + if (scriptId != null) { + return sendCommandAndValidateResult( + remoteDebugger, + method: 'Debugger.setBreakpoint', + resultField: 'breakpointId', + params: { + 'location': { + 'lineNumber': location.jsLocation.line, + 'columnNumber': location.jsLocation.column, + 'scriptId': scriptId, + }, + }, + ); + } else { + _logger.fine('No runtime script ID for location $location'); + return null; + } }); } diff --git a/dwds/lib/src/debugging/location.dart b/dwds/lib/src/debugging/location.dart index 161573c6e..c055dee69 100644 --- a/dwds/lib/src/debugging/location.dart +++ b/dwds/lib/src/debugging/location.dart @@ -33,6 +33,7 @@ class Location { TargetLineEntry lineEntry, TargetEntry entry, DartUri dartUri, + String? runtimeScriptId, ) { final dartLine = entry.sourceLine; final dartColumn = entry.sourceColumn; @@ -42,7 +43,7 @@ class Location { // lineEntry data is 0 based according to: // https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k return Location._( - JsLocation.fromZeroBased(module, jsLine, jsColumn), + JsLocation.fromZeroBased(module, jsLine, jsColumn, runtimeScriptId), DartLocation.fromZeroBased(dartUri, dartLine ?? 0, dartColumn ?? 0), ); } @@ -104,10 +105,16 @@ class JsLocation { /// 0 based column offset within the JS source code. final int column; + /// The Runtime.ScriptId of a script in Chrome. + /// + /// See https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-ScriptId + String? runtimeScriptId; + JsLocation._( this.module, this.line, this.column, + this.runtimeScriptId, ); int compareTo(JsLocation other) => compareToLine(other.line, other.column); @@ -122,8 +129,13 @@ class JsLocation { // JS Location is 0 based according to: // https://chromedevtools.github.io/devtools-protocol/tot/Debugger#type-Location - factory JsLocation.fromZeroBased(String module, int line, int column) => - JsLocation._(module, line, column); + factory JsLocation.fromZeroBased( + String module, + int line, + int column, + String? runtimeScriptId, + ) => + JsLocation._(module, line, column, runtimeScriptId); } /// Contains meta data for known [Location]s. @@ -321,6 +333,10 @@ class Locations { p.url.dirname('/${stripLeadingSlashes(modulePath)}'); if (sourceMapContents == null) return result; + + final runtimeScriptId = + await _modules.getRuntimeScriptIdForModule(_entrypoint, module); + // This happens to be a [SingleMapping] today in DDC. final mapping = parse(sourceMapContents); if (mapping is SingleMapping) { @@ -339,12 +355,14 @@ class Locations { ); final dartUri = DartUri(path, _root); + result.add( Location.from( modulePath, lineEntry, entry, dartUri, + runtimeScriptId, ), ); } diff --git a/dwds/lib/src/debugging/modules.dart b/dwds/lib/src/debugging/modules.dart index 37b857af1..5ec0afdc3 100644 --- a/dwds/lib/src/debugging/modules.dart +++ b/dwds/lib/src/debugging/modules.dart @@ -4,6 +4,7 @@ import 'package:async/async.dart'; import 'package:dwds/src/config/tool_configuration.dart'; +import 'package:dwds/src/debugging/debugger.dart'; import 'package:dwds/src/utilities/dart_uri.dart'; import 'package:logging/logging.dart'; @@ -62,6 +63,15 @@ class Modules { return _sourceToModule; } + Future getRuntimeScriptIdForModule( + String entrypoint, + String module, + ) async { + final serverPath = await globalToolConfiguration.loadStrategy + .serverPathForModule(entrypoint, module); + return chromePathToRuntimeScriptId[serverPath]; + } + /// Initializes [_sourceToModule] and [_sourceToLibrary]. Future _initializeMapping() async { final provider = diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 94d690c8c..9e2511dba 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -99,9 +99,6 @@ class ChromeProxyService implements VmServiceInterface { Stream get pauseIsolatesOnStartStream => _pauseIsolatesOnStartController.stream; - final _disabledBreakpoints = {}; - final _previousBreakpoints = {}; - final _logger = Logger('ChromeProxyService'); final ExpressionCompiler? _compiler; @@ -295,12 +292,6 @@ class ChromeProxyService implements VmServiceInterface { safeUnawaited(_prewarmExpressionCompilerCache()); - await debugger.reestablishBreakpoints( - _previousBreakpoints, - _disabledBreakpoints, - ); - _disabledBreakpoints.clear(); - safeUnawaited( appConnection.onStart.then((_) { debugger.resumeFromStart(); @@ -376,19 +367,15 @@ class ChromeProxyService implements VmServiceInterface { ); _vm.isolates?.removeWhere((ref) => ref.id == isolate.id); _inspector = null; - _previousBreakpoints.clear(); - _previousBreakpoints.addAll(isolate.breakpoints ?? []); _expressionEvaluator?.close(); _consoleSubscription?.cancel(); _consoleSubscription = null; } Future disableBreakpoints() async { - _disabledBreakpoints.clear(); if (!_isIsolateRunning) return; final isolate = inspector.isolate; - _disabledBreakpoints.addAll(isolate.breakpoints ?? []); for (var breakpoint in isolate.breakpoints?.toList() ?? []) { await (await debuggerFuture).removeBreakpoint(breakpoint.id); } @@ -1121,8 +1108,6 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer. ) async { await isInitialized; _checkIsolate('removeBreakpoint', isolateId); - _disabledBreakpoints - .removeWhere((breakpoint) => breakpoint.id == breakpointId); return (await debuggerFuture).removeBreakpoint(breakpointId); } diff --git a/dwds/test/fixtures/fakes.dart b/dwds/test/fixtures/fakes.dart index a24381d7a..50e5eba81 100644 --- a/dwds/test/fixtures/fakes.dart +++ b/dwds/test/fixtures/fakes.dart @@ -169,6 +169,13 @@ class FakeModules implements Modules { @override Future moduleForLibrary(String libraryUri) async => _module; + + @override + Future getRuntimeScriptIdForModule( + String entrypoint, + String module, + ) async => + null; } class FakeWebkitDebugger implements WebkitDebugger { diff --git a/dwds/test/location_test.dart b/dwds/test/location_test.dart index bfa0ecfda..28cf8323f 100644 --- a/dwds/test/location_test.dart +++ b/dwds/test/location_test.dart @@ -36,17 +36,24 @@ void main() { locations.initialize('fake_entrypoint'); group('JS locations |', () { + const fakeRuntimeScriptId = '12'; + group('location |', () { - test('is zero based', () async { - final loc = JsLocation.fromZeroBased(_module, 0, 0); + test('is zero based', () { + final loc = + JsLocation.fromZeroBased(_module, 0, 0, fakeRuntimeScriptId); expect(loc, _matchJsLocation(0, 0)); }); - test('can compare to other location', () async { - final loc00 = JsLocation.fromZeroBased(_module, 0, 0); - final loc01 = JsLocation.fromZeroBased(_module, 0, 1); - final loc10 = JsLocation.fromZeroBased(_module, 1, 0); - final loc11 = JsLocation.fromZeroBased(_module, 1, 1); + test('can compare to other location', () { + final loc00 = + JsLocation.fromZeroBased(_module, 0, 0, fakeRuntimeScriptId); + final loc01 = + JsLocation.fromZeroBased(_module, 0, 1, fakeRuntimeScriptId); + final loc10 = + JsLocation.fromZeroBased(_module, 1, 0, fakeRuntimeScriptId); + final loc11 = + JsLocation.fromZeroBased(_module, 1, 1, fakeRuntimeScriptId); expect(loc00.compareTo(loc01), isNegative); expect(loc00.compareTo(loc10), isNegative); diff --git a/dwds/test/reload_test.dart b/dwds/test/reload_test.dart index 32b969326..2961273e7 100644 --- a/dwds/test/reload_test.dart +++ b/dwds/test/reload_test.dart @@ -376,68 +376,22 @@ void main() { isolateId = vm.isolates!.first.id!; final isolate = await client.getIsolate(isolateId); - // Previous breakpoint should still exist. - expect(isolate.breakpoints!.isNotEmpty, isTrue); - final bp = isolate.breakpoints!.first; - - // Should pause eventually. - await stream - .firstWhere((event) => event.kind == EventKind.kPauseBreakpoint); - - expect( - await client.removeBreakpoint(isolate.id!, bp.id!), - isA(), - ); - expect(await client.resume(isolate.id!), isA()); + // Previous breakpoint should be cleared. + expect(isolate.breakpoints!.isEmpty, isTrue); }); - test('can evaluate expressions after hot restart ', () async { + test('can evaluate expressions after hot restart', () async { final client = context.debugConnection.vmService; - var vm = await client.getVM(); - var isolateId = vm.isolates!.first.id!; - await client.streamListen('Debug'); - final stream = client.onEvent('Debug'); - final scriptList = await client.getScripts(isolateId); - final main = scriptList.scripts! - .firstWhere((script) => script.uri!.contains('main.dart')); - final bpLine = - await context.findBreakpointLine('printCount', isolateId, main); - await client.addBreakpoint(isolateId, main.id!, bpLine); - await stream - .firstWhere((event) => event.kind == EventKind.kPauseBreakpoint); await client.callServiceExtension('hotRestart'); - vm = await client.getVM(); - isolateId = vm.isolates!.first.id!; + final vm = await client.getVM(); + final isolateId = vm.isolates!.first.id!; final isolate = await client.getIsolate(isolateId); final library = isolate.rootLib!.uri!; - final bp = isolate.breakpoints!.first; - - // Should pause eventually. - final event = await stream - .firstWhere((event) => event.kind == EventKind.kPauseBreakpoint); - - // Expression evaluation while paused on a breakpoint should work. - var result = await client.evaluateInFrame( - isolate.id!, - event.topFrame!.index!, - 'count', - ); - expect( - result, - isA().having( - (instance) => instance.valueAsString, - 'valueAsString', - greaterThanOrEqualTo('0'), - ), - ); - - await client.removeBreakpoint(isolateId, bp.id!); - await client.resume(isolateId); // Expression evaluation while running should work. - result = await client.evaluate(isolateId, library, 'true'); + final result = await client.evaluate(isolateId, library, 'true'); expect( result, isA().having( diff --git a/dwds/test/restore_breakpoints_test.dart b/dwds/test/restore_breakpoints_test.dart deleted file mode 100644 index 5070c47e1..000000000 --- a/dwds/test/restore_breakpoints_test.dart +++ /dev/null @@ -1,124 +0,0 @@ -// 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. - -@TestOn('vm') -@Timeout(Duration(minutes: 2)) -import 'dart:async'; - -import 'package:test/test.dart'; -import 'package:test_common/logging.dart'; -import 'package:test_common/test_sdk_configuration.dart'; -import 'package:vm_service/vm_service.dart'; -import 'package:vm_service_interface/vm_service_interface.dart'; - -import 'fixtures/context.dart'; -import 'fixtures/project.dart'; - -void main() { - final provider = TestSdkConfigurationProvider(); - tearDownAll(provider.dispose); - - final context = TestContext(TestProject.testWithSoundNullSafety, provider); - - setUpAll(() async { - setCurrentLogWriter(); - await context.setUp(); - }); - - tearDownAll(() async { - await context.tearDown(); - }); - - group('breakpoints', () { - late VmServiceInterface service; - VM vm; - late Isolate isolate; - ScriptList scripts; - late ScriptRef mainScript; - late Stream isolateEventStream; - - setUp(() async { - setCurrentLogWriter(); - service = context.service; - vm = await service.getVM(); - isolate = await service.getIsolate(vm.isolates!.first.id!); - scripts = await service.getScripts(isolate.id!); - mainScript = scripts.scripts! - .firstWhere((each) => each.uri!.contains('main.dart')); - isolateEventStream = service.onEvent('Isolate'); - }); - - tearDown(() async { - // Remove breakpoints so they don't impact other tests. - for (var breakpoint in isolate.breakpoints!.toList()) { - await service.removeBreakpoint(isolate.id!, breakpoint.id!); - } - }); - - test( - 'restore after refresh', - () async { - final firstBp = - await service.addBreakpoint(isolate.id!, mainScript.id!, 23); - expect(firstBp, isNotNull); - expect(firstBp.id, isNotNull); - - final eventsDone = expectLater( - isolateEventStream, - emitsThrough( - emitsInOrder([ - predicate((Event event) => event.kind == EventKind.kIsolateExit), - predicate((Event event) => event.kind == EventKind.kIsolateStart), - predicate( - (Event event) => event.kind == EventKind.kIsolateRunnable, - ), - ]), - ), - ); - - await context.webDriver.refresh(); - await eventsDone; - - vm = await service.getVM(); - isolate = await service.getIsolate(vm.isolates!.first.id!); - - expect(isolate.breakpoints!.length, equals(1)); - }, - timeout: const Timeout.factor(2), - ); - - test( - 'restore after hot restart', - () async { - final firstBp = - await service.addBreakpoint(isolate.id!, mainScript.id!, 23); - expect(firstBp, isNotNull); - expect(firstBp.id, isNotNull); - - final eventsDone = expectLater( - isolateEventStream, - emits( - emitsInOrder([ - predicate((Event event) => event.kind == EventKind.kIsolateExit), - predicate((Event event) => event.kind == EventKind.kIsolateStart), - predicate( - (Event event) => event.kind == EventKind.kIsolateRunnable, - ), - ]), - ), - ); - - await context.debugConnection.vmService - .callServiceExtension('hotRestart'); - await eventsDone; - - vm = await service.getVM(); - isolate = await service.getIsolate(vm.isolates!.first.id!); - - expect(isolate.breakpoints!.length, equals(1)); - }, - timeout: const Timeout.factor(2), - ); - }); -} diff --git a/dwds/test/skip_list_test.dart b/dwds/test/skip_list_test.dart index f4bb01b12..99f09e1d8 100644 --- a/dwds/test/skip_list_test.dart +++ b/dwds/test/skip_list_test.dart @@ -16,24 +16,27 @@ void main() { setGlobalsForTesting(); late SkipLists skipLists; final dartUri = DartUri('org-dartlang-app://web/main.dart'); + const fakeRuntimeScriptId = '12'; group('SkipLists', () { setUp(() { skipLists = SkipLists(); }); - test('do not include known ranges', () async { + test('do not include known ranges', () { final skipList = skipLists.compute('123', { Location.from( 'foo', TargetLineEntry(1, []), TargetEntry(2, 0, 0, 0), dartUri, + fakeRuntimeScriptId, ), Location.from( 'foo', TargetLineEntry(10, []), TargetEntry(20, 0, 0, 0), dartUri, + fakeRuntimeScriptId, ), }); expect(skipList.length, 3); @@ -42,19 +45,21 @@ void main() { _validateRange(skipList.last, 10, 21, maxValue, maxValue); }); - test('do not include start of the file', () async { + test('do not include start of the file', () { final skipList = skipLists.compute('123', { Location.from( 'foo', TargetLineEntry(0, []), TargetEntry(0, 0, 0, 0), dartUri, + fakeRuntimeScriptId, ), Location.from( 'foo', TargetLineEntry(10, []), TargetEntry(20, 0, 0, 0), dartUri, + fakeRuntimeScriptId, ), }); expect(skipList.length, 2); @@ -62,19 +67,21 @@ void main() { _validateRange(skipList.last, 10, 21, maxValue, maxValue); }); - test('does not depend on order of locations', () async { + test('does not depend on order of locations', () { final skipList = skipLists.compute('123', { Location.from( 'foo', TargetLineEntry(10, []), TargetEntry(20, 0, 0, 0), dartUri, + fakeRuntimeScriptId, ), Location.from( 'foo', TargetLineEntry(0, []), TargetEntry(0, 0, 0, 0), dartUri, + fakeRuntimeScriptId, ), }); expect(skipList.length, 2); @@ -82,7 +89,7 @@ void main() { _validateRange(skipList.last, 10, 21, maxValue, maxValue); }); - test('contains the provided id', () async { + test('contains the provided id', () { final id = '123'; final skipList = skipLists.compute(id, {}); for (var range in skipList) { @@ -90,7 +97,7 @@ void main() { } }); - test('ignores the whole file if provided no locations', () async { + test('ignores the whole file if provided no locations', () { final skipList = skipLists.compute('123', {}); expect(skipList.length, 1); _validateRange(skipList.first, 0, 0, maxValue, maxValue);