From 2423f86a4c42b54b1eec7d0acd64d2241bf153e6 Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Thu, 4 Jan 2018 16:33:52 -0800 Subject: [PATCH] Use VMScriptRef to identify VM scripts, not URI Previously, coverage collection assumed that a script could be uniquely identified by URI, which is not a valid assumption. For example, when a part is loaded via two libraries, both of which are loaded by an isolate, the VM will track these are two scripts that map to the same URI. During collection, we now track each script by its (unique) VMScriptRef. This ensures we lookup the correct script when computing the affected line for each hit token. The hitmap remains URI based, since in the end, we want a single, unified set of line->hitCount mappings per script. Fixes dart-lang/coverage#194 --- lib/src/collect.dart | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/src/collect.dart b/lib/src/collect.dart index 1b231383..6aea9d71 100644 --- a/lib/src/collect.dart +++ b/lib/src/collect.dart @@ -80,10 +80,9 @@ Future _waitIsolatesPaused(VMServiceClient service, {Duration timeout}) async { Future>> _getCoverageJson( VMServiceClient service, VMSourceReport report) async { var scriptRefs = report.ranges.map((r) => r.script).toSet(); - var scripts = {}; - for (var script in await Future.wait( - scriptRefs.map((ref) => ref.load()).toList())) { - scripts[script.uri] = script; + var scripts = {}; + for (var ref in scriptRefs) { + scripts[ref] = await ref.load(); } // script uri -> { line -> hit count } @@ -94,7 +93,7 @@ Future>> _getCoverageJson( hitMaps.putIfAbsent(range.script.uri, () => {}); var hitMap = hitMaps[range.script.uri]; - var script = scripts[range.script.uri]; + var script = scripts[range.script]; for (VMScriptToken hit in range.hits ?? []) { var line = script.sourceLocation(hit).line + 1; hitMap[line] = hitMap.containsKey(line) ? hitMap[line] + 1 : 1; @@ -108,27 +107,26 @@ Future>> _getCoverageJson( // Output JSON var coverage = >[]; hitMaps.forEach((uri, hitMap) { - var script = scripts[uri]; - coverage.add(_toScriptCoverageJson(script, hitMap)); + coverage.add(_toScriptCoverageJson(uri, hitMap)); }); return coverage; } /// Returns a JSON hit map backward-compatible with pre-1.16.0 SDKs. Map _toScriptCoverageJson( - VMScript script, Map hitMap) { + Uri scriptUri, Map hitMap) { var json = {}; var hits = []; hitMap.forEach((line, hitCount) { hits.add(line); hits.add(hitCount); }); - json['source'] = '${script.uri}'; + json['source'] = '$scriptUri'; json['script'] = { 'type': '@Script', 'fixedId': true, - 'id': 'libraries/1/scripts/${Uri.encodeComponent(script.uri.toString())}', - 'uri': '${script.uri}', + 'id': 'libraries/1/scripts/${Uri.encodeComponent(scriptUri.toString())}', + 'uri': '$scriptUri', '_kind': 'library', }; json['hits'] = hits;